github.com/latentflip/deval
Sometimes you're doing interesting things, and you want a block of code as a multiline string.
But doing this is super annoying:
var codeString = [
"var foo = 'bar'",
"function stuff () {",
" console.log('The thing is \"10\"');"
"}"
].join('\n');
Quotes everywhere, keeping track of indentation is a pain if you want it properly formatted, no syntax highlighting.
Function code to string makes it look like this:
var codeToString = require('codeToString');
var codeString = codeToString(function () {
var foo = 'bar';
function stuff () {
console.log('The thing is "10"');
}
});
// codeString -> "var foo = 'bar';\nfunction stuff () {\n console.log('The thing is \"10\"');\n}"
It even figures out what indentation you meant and cleans that up.
If eval() takes a string representing code, and turns it into actual code, codeToString() takes actual code, and returns a string representation of it.
Basic usage.
Call codeToString() with a function containing the code you want to get back as a string.
The function wrapper will be removed.
var codeToString = require('codeToString');
var codeString = codeToString(function(){
var foo = 'bar';
function stuff () {
console.log('The thing is "10"');
}
});
// codeString will be:
// "var foo = 'bar';
// function stuff () {
// console.log('The thing is \"10\"');
// }"
Advanced usage.
Sometimes you want to interpolate strings / numbers / etc into your generated code.
You can't just use normal scoping rules, because this code won't be executed in the current scope.
So instead you can do a little templating magic.
To interpolate:
- Name some positional arguments in the function you pass to codeToString: codeToString(function (arg1, arg2) { ...
- Insert them where you want them in your code by wrapping in dollars: $arg1$
- Pass the values of those arguments as additional arguments to codeToString itself. codeToString(function (arg1, arg2) { ... }, "one", 2)
var codeString = codeToString(function (foo, bar) {
var thing = $bar$;
console.log('$foo$');
console.log(thing);
}, "hi", 5);
// codeString will be:
// "var thing = 5;
// console.log('hi');
// console.log(thing)"
Don't try to be too clever with this, and if you're passing strings, you'll want to wrap them in quotes inside the code block, as shown about for "hi" -> '$foo$'
Source Code of codeToString():
var min = function (arr) {return Math.min.apply(Math, arr);};
var REGEXES = {
functionOpening: /^function\s*\((.*)\)[^{]{/
};
module.exports = function (fn/*, interpolateArgs... */) {
var str = fn.toString();
var interpolateArgs = Array.prototype.slice.call(arguments, 1);
var argNames;
if (interpolateArgs.length) {argNames = getArgumentNames(str);}
str = removeFunctionWrapper(str);
str = dedent(str);
if (argNames && argNames.length) {str = interpolate(str, argNames, interpolateArgs);}
return str;
};
function getArgumentNames (str) {
var argStr = str.match(REGEXES.functionOpening);
return argStr[1].split(',').map(function (s) { return s.trim(); });
}
function removeFunctionWrapper (str) {
var closingBraceIdx, finalNewlineIdx, lastLine;
// remove opening function bit
str = str.replace(REGEXES.functionOpening, '');
// remove closing function brace
closingBraceIdx = str.lastIndexOf('}');
if (closingBraceIdx > 0) {str = str.slice(0, closingBraceIdx - 1);}
// If there was no code on opening wrapper line, remove it
str = str.replace(/^[^\S\n]*\n/, '');
// If there was no code on final line, remove it
finalNewlineIdx = str.lastIndexOf('\n');
lastLine = str.slice(finalNewlineIdx);
if (lastLine.trim() === '') str = str.slice(0, finalNewlineIdx);
return str;
}
// Reset indent on the code to minimum possible
function dedent (str) {
var lines = str.split('\n');
var indent = min(lines.map(function (line) {return line.match(/^\s*/)[0].length;}));
lines = lines.map(function (line) {return line.slice(indent);});
return lines.join('\n');
}
function interpolate (str, argNames, args) {
argNames.forEach(function (name, i) {
var regex = new RegExp('\\$' + name + '\\$', 'g');
str = str.replace(regex, args[i]);
});
return str;
}
Tests:
var test = require('tape');
var codeToString = require('./codeToString');
test('it serializes multiline code', function (t) {
var serialized = codeToString(function () {
console.log('hi');
console.log('there');
});
var expected = [
"console.log('hi');",
"console.log('there');"
].join('\n');
t.equal(serialized, expected);
t.end();
});
test('it serializes inline code', function (t) {
var serialized = codeToString(function () { console.log('hi'); console.log('there'); });
var expected = [
"console.log('hi'); console.log('there');"
].join('\n');
t.equal(serialized, expected);
t.end();
});
test('it even interpolates things', function (t) {
var serialized = codeToString(function (foo, bar) {
console.log('$foo$');
console.log($bar$);
}, "hi", 5);
var expected = [
"console.log('hi');",
"console.log(5);"
].join('\n');
t.equal(serialized, expected);
t.end();
});
среда, 13 апреля 2016 г.
JavaScript Code Execution Visualization
latentflip.com/loupe
github.com/latentflip/loupe
pythontutor.com/javascript.html#mode=edit
github.com/latentflip/loupe
pythontutor.com/javascript.html#mode=edit
JavaScript Turing Machine
All it needs are some instructions, the initial state of the tape as a list, an end state and a start state. It will return either the final tape state or false if the end state is never reached. ‘B’ is considered a blank state and the tape behaves as infinite in both directions.
function tm (I, tape, end, state, i, cell, current) {
i = 0;
while (state != end) {
cell = tape[i];
current = (cell) ? I[state][cell] : I[state].B;
if (!current) {return false;}
tape.splice(i, 1, current.w);
i += current.m;
state = current.n;
}
return tape;
}
// For testing purposes, run in Node.js as command:
// node turing-140.js machine-140.json 111 q5
// Instructions tape endstate.
console.log(
tm(
JSON.parse(
require('fs').readFileSync(process.argv[2], 'utf-8')
)
, process.argv[3].split("")
, process.argv[4]
, "q0"
).join("")
);
For testing use a simple multiply program that basically turns 111 into 1110111. So this is what the algorithm’s implementation ends up looking like
{
"q0": {"1": {"w": "B", "m": 1, "n": "q1"}},
"q1": {"1": {"w": "1", "m": 1, "n": "q1"},
"0": {"w": "0", "m": 1, "n": "q2"},
"B": {"w": "0", "m": 1, "n": "q2"}},
"q2": {"1": {"w": "1", "m": 1, "n": "q2"},
"B": {"w": "1", "m": -1, "n": "q3"}},
"q3": {"1": {"w": "1", "m": -1, "n": "q3"},
"0": {"w": "0", "m": -1, "n": "q3"},
"B": {"w": "1", "m": 1, "n": "q4"}},
"q4": {"1": {"w": "B", "m": 1, "n": "q1"},
"0": {"w": "0", "m": 1, "n": "q5"}}
}
There’s a smaller solution of Turing Machine in a less verbose language:
function(a,b,c,d,e){for(e=0;d<c;)with(a[d][b[e]||"B"])b[e]=w,e+=m,d=n;return b}
function tm (I, tape, end, state, i, cell, current) {
i = 0;
while (state != end) {
cell = tape[i];
current = (cell) ? I[state][cell] : I[state].B;
if (!current) {return false;}
tape.splice(i, 1, current.w);
i += current.m;
state = current.n;
}
return tape;
}
// For testing purposes, run in Node.js as command:
// node turing-140.js machine-140.json 111 q5
// Instructions tape endstate.
console.log(
tm(
JSON.parse(
require('fs').readFileSync(process.argv[2], 'utf-8')
)
, process.argv[3].split("")
, process.argv[4]
, "q0"
).join("")
);
For testing use a simple multiply program that basically turns 111 into 1110111. So this is what the algorithm’s implementation ends up looking like
{
"q0": {"1": {"w": "B", "m": 1, "n": "q1"}},
"q1": {"1": {"w": "1", "m": 1, "n": "q1"},
"0": {"w": "0", "m": 1, "n": "q2"},
"B": {"w": "0", "m": 1, "n": "q2"}},
"q2": {"1": {"w": "1", "m": 1, "n": "q2"},
"B": {"w": "1", "m": -1, "n": "q3"}},
"q3": {"1": {"w": "1", "m": -1, "n": "q3"},
"0": {"w": "0", "m": -1, "n": "q3"},
"B": {"w": "1", "m": 1, "n": "q4"}},
"q4": {"1": {"w": "B", "m": 1, "n": "q1"},
"0": {"w": "0", "m": 1, "n": "q5"}}
}
There’s a smaller solution of Turing Machine in a less verbose language:
function(a,b,c,d,e){for(e=0;d<c;)with(a[d][b[e]||"B"])b[e]=w,e+=m,d=n;return b}
пятница, 1 апреля 2016 г.
JavaScript Observer, Iterator, Generator, Promise and Observable Patterns
Итератор перебирает подряд набор значений и по очереди выдает элементы iterator.next(), как array.shift()
Генератор по очереди принимает элементы generator.next(1), как array.push(1)
Промис по очереди выполняет цепочку зависимых друг от друга асинхронных событий
Обозреватель добавляет к объекту к объекту функцию события и вызывает её, когда это событие генерируется в коде.
Обозреваемое добавляет к последовательности элементов или асинхронных событий итератор, который по порядку перебирает элементы и обозреватель, который вызывает для перебираемых элементов функции события.
Декоратор обертывает одну функцию в другую функцию decorate(base, wrapper).
Фабрика конструирует объекты по заданным параметрам.
Фасад скрывает сложную функциональность, выдавая вместо неё простую функцию.
Прокси оборачивает функцию в декоратор.
Observer Pattern
// Observer
function Observer () {
this.events = {};
}
Observer.prototype = {
addEvent: function (name, func) {if (this.events[name]) {this.events[name].push(func);} else {this.events[name] = [func];}}
, removeEvent: function (name) {if (this.events[name]) {delete this.events[name];}}
, dispatchEvent: function (name, args) {if (this.events[name]) {this.events[name].forEach(function (func) {func.apply(null, args);});}}
};
// Observer Test
var observer = new Observer();
observer.addEvent('one', function (a) {console.log('1: ' + a);});
observer.addEvent('one', function (b) {console.log('2: ' + b);});
observer.addEvent('two', function (c) {console.log('3: ' + c);});
observer.dispatchEvent('one', ['one']);
observer.dispatchEvent('two', ['two']);
observer.removeEvent('one');
observer.dispatchEvent('one', ['one']);
Iterator Pattern
// Iterator
function Iterator (items) {
var i = 0;
return {
next: function () {
var done = (i >= items.length)
, value = !done ? items[i++] : undefined;
return {value: value, done: done};
}
};
}
// Iterator Test
var iterator = new Iterator([1, 2, 3]);
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
Generator Pattern
// Generator
function Generator (items) {
var i = 0;
return {
next: function (value) {
items = items.slice();
var done = (i >= items.length)
if (!done) {items[i] = value; i++;}
return {value: items, done: done};
}
};
}
// Generator Test
var generator = new Generator(new Array(3));
console.log(generator.next(1)); // {value: [1, undefined, undefined], done: false}
console.log(generator.next(2)); // {value: [1, 2, undefined], done: false}
console.log(generator.next(3)); // {value: [1, 2, 3], done: false}
console.log(generator.next(4)); // {value: [1, 2, 3], done: true}
Promise Pattern
// Promise
function Promise () {
this.promises = [];
}
Promise.prototype = {
then: function (success, error) {
if (Object.prototype.toString.call(success) !== '[object Function]') {success = function () {};}
if (Object.prototype.toString.call(error) !== '[object Function]') {error = function () {};}
this.promises.push({success: success, error: error});
return this;
}
, success: function () {
if (this.promises.length) {
var args = Array.prototype.slice.call(arguments);
args.unshift(this);
this.promises.shift().success.apply(null, args);
}
}
, error: function () {
if (this.promises.length) {
this.promises.shift().error.apply(null, arguments);
}
}
};
// Promise Test
function timeout1 (seconds, error) {
var promise = new Promise();
setTimeout(function () {
if (seconds > 2) {
promise.error(seconds);
} else {
console.log('Success 1: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function timeout2 (promise, seconds) {
setTimeout(function () {
if (seconds > 2) {
promise.error(seconds);
} else {
console.log('Success 2: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function timeout3 (promise, seconds) {
setTimeout(function () {
if (seconds > 1) {
promise.error(seconds);
} else {
console.log('Success 3: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function done (promise, seconds) {
console.log('Done: ' + seconds);
}
function timeout1error (seconds) {console.log('Error 1 seconds: ' + seconds);}
function timeout2error (seconds) {console.log('Error 2 seconds: ' + seconds);}
function timeout3error (seconds) {console.log('Error 3 seconds: ' + seconds);}
timeout1(2).then(timeout2, timeout1error).then(timeout3, timeout2error).then(done, timeout3error);
Observable Pattern = Interator + Promise for async + Observer
Перебираем с помощью итератора все элементы массива или цепочки промисов и для каждого из них тригерим подставленные функции события (успешно, неуспешно, завершено).
// Observable
var Observable = {
from: function (items) {
var iterator = new Iterator(items);
return {subscribe: function (next, error, complete) {
var item = iterator.next();
while (!item.done) {
next(item.value);
item = iterator.next();
}
complete();
}};
}
};
// Observable Test
Observable.from(['Adria', 'Jen', 'Sergi']).subscribe(
function onNext (value) {console.log('Next: ' + value);}
, function onError (error) {console.log('Error: ' + error);}
, function onCompleted () {console.log('Completed');}
);
Генератор по очереди принимает элементы generator.next(1), как array.push(1)
Промис по очереди выполняет цепочку зависимых друг от друга асинхронных событий
Обозреватель добавляет к объекту к объекту функцию события и вызывает её, когда это событие генерируется в коде.
Обозреваемое добавляет к последовательности элементов или асинхронных событий итератор, который по порядку перебирает элементы и обозреватель, который вызывает для перебираемых элементов функции события.
Декоратор обертывает одну функцию в другую функцию decorate(base, wrapper).
Фабрика конструирует объекты по заданным параметрам.
Фасад скрывает сложную функциональность, выдавая вместо неё простую функцию.
Прокси оборачивает функцию в декоратор.
Observer Pattern
// Observer
function Observer () {
this.events = {};
}
Observer.prototype = {
addEvent: function (name, func) {if (this.events[name]) {this.events[name].push(func);} else {this.events[name] = [func];}}
, removeEvent: function (name) {if (this.events[name]) {delete this.events[name];}}
, dispatchEvent: function (name, args) {if (this.events[name]) {this.events[name].forEach(function (func) {func.apply(null, args);});}}
};
// Observer Test
var observer = new Observer();
observer.addEvent('one', function (a) {console.log('1: ' + a);});
observer.addEvent('one', function (b) {console.log('2: ' + b);});
observer.addEvent('two', function (c) {console.log('3: ' + c);});
observer.dispatchEvent('one', ['one']);
observer.dispatchEvent('two', ['two']);
observer.removeEvent('one');
observer.dispatchEvent('one', ['one']);
Iterator Pattern
// Iterator
function Iterator (items) {
var i = 0;
return {
next: function () {
var done = (i >= items.length)
, value = !done ? items[i++] : undefined;
return {value: value, done: done};
}
};
}
// Iterator Test
var iterator = new Iterator([1, 2, 3]);
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
Generator Pattern
// Generator
function Generator (items) {
var i = 0;
return {
next: function (value) {
items = items.slice();
var done = (i >= items.length)
if (!done) {items[i] = value; i++;}
return {value: items, done: done};
}
};
}
// Generator Test
var generator = new Generator(new Array(3));
console.log(generator.next(1)); // {value: [1, undefined, undefined], done: false}
console.log(generator.next(2)); // {value: [1, 2, undefined], done: false}
console.log(generator.next(3)); // {value: [1, 2, 3], done: false}
console.log(generator.next(4)); // {value: [1, 2, 3], done: true}
Promise Pattern
// Promise
function Promise () {
this.promises = [];
}
Promise.prototype = {
then: function (success, error) {
if (Object.prototype.toString.call(success) !== '[object Function]') {success = function () {};}
if (Object.prototype.toString.call(error) !== '[object Function]') {error = function () {};}
this.promises.push({success: success, error: error});
return this;
}
, success: function () {
if (this.promises.length) {
var args = Array.prototype.slice.call(arguments);
args.unshift(this);
this.promises.shift().success.apply(null, args);
}
}
, error: function () {
if (this.promises.length) {
this.promises.shift().error.apply(null, arguments);
}
}
};
// Promise Test
function timeout1 (seconds, error) {
var promise = new Promise();
setTimeout(function () {
if (seconds > 2) {
promise.error(seconds);
} else {
console.log('Success 1: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function timeout2 (promise, seconds) {
setTimeout(function () {
if (seconds > 2) {
promise.error(seconds);
} else {
console.log('Success 2: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function timeout3 (promise, seconds) {
setTimeout(function () {
if (seconds > 1) {
promise.error(seconds);
} else {
console.log('Success 3: ' + seconds);
promise.success(seconds);
}
}, seconds * 1000);
return promise;
}
function done (promise, seconds) {
console.log('Done: ' + seconds);
}
function timeout1error (seconds) {console.log('Error 1 seconds: ' + seconds);}
function timeout2error (seconds) {console.log('Error 2 seconds: ' + seconds);}
function timeout3error (seconds) {console.log('Error 3 seconds: ' + seconds);}
timeout1(2).then(timeout2, timeout1error).then(timeout3, timeout2error).then(done, timeout3error);
Observable Pattern = Interator + Promise for async + Observer
Перебираем с помощью итератора все элементы массива или цепочки промисов и для каждого из них тригерим подставленные функции события (успешно, неуспешно, завершено).
// Observable
var Observable = {
from: function (items) {
var iterator = new Iterator(items);
return {subscribe: function (next, error, complete) {
var item = iterator.next();
while (!item.done) {
next(item.value);
item = iterator.next();
}
complete();
}};
}
};
// Observable Test
Observable.from(['Adria', 'Jen', 'Sergi']).subscribe(
function onNext (value) {console.log('Next: ' + value);}
, function onError (error) {console.log('Error: ' + error);}
, function onCompleted () {console.log('Completed');}
);
вторник, 29 марта 2016 г.
Error handling in JavaScript
Modern Chrome and Opera fully support the HTML 5 draft spec for ErrorEvent and window.onerror. In both of these browsers you can either use window.onerror, or bind to the 'error' event properly:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendError(data);
})
Unfortunately Firefox, Safari and IE are still around and we have to support them too. As the stacktrace is not available in window.onerror we have to do a little bit more work.
It turns out that the only thing we can do to get stacktraces from errors is to wrap all of our code in a try{ }catch(e){ } block and then look at e.stack. We can make the process somewhat easier with a function called wrap that takes a function and returns a new function with good error handling.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
This works. Any function that you wrap manually will have good error handling, but it turns out that we can actually do it for you automatically in most cases.
By changing the global definition of addEventListener so that it automatically wraps the callback we can automatically insert try{ }catch(e){ } around most code. This lets existing code continue to work, but adds high-quality exception tracking.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
We also need to make sure that removeEventListener keeps working. At the moment it won't because the argument to addEventListener is changed. Again we only need to fix this on the prototype object:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Transmit error data to your backend
You can send error data using image tag as follows
function sendError(data) {
var img = newImage(),
src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.log(message, "from", error.stack);
// You can send data to your server
// sendError(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.log(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendError(data);
})
Unfortunately Firefox, Safari and IE are still around and we have to support them too. As the stacktrace is not available in window.onerror we have to do a little bit more work.
It turns out that the only thing we can do to get stacktraces from errors is to wrap all of our code in a try{ }catch(e){ } block and then look at e.stack. We can make the process somewhat easier with a function called wrap that takes a function and returns a new function with good error handling.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.log(e.message, "from", e.stack);
// You can send data to your server
// sendError(data);
throw e;
}
}
}
return func._wrapped;
};
This works. Any function that you wrap manually will have good error handling, but it turns out that we can actually do it for you automatically in most cases.
By changing the global definition of addEventListener so that it automatically wraps the callback we can automatically insert try{ }catch(e){ } around most code. This lets existing code continue to work, but adds high-quality exception tracking.
var addEventListener = window.EventTarget.prototype.addEventListener;
window.EventTarget.prototype.addEventListener = function (event, callback, bubble) {
addEventListener.call(this, event, wrap(callback), bubble);
}
We also need to make sure that removeEventListener keeps working. At the moment it won't because the argument to addEventListener is changed. Again we only need to fix this on the prototype object:
var removeEventListener = window.EventTarget.prototype.removeEventListener;
window.EventTarget.prototype.removeEventListener = function (event, callback, bubble) {
removeEventListener.call(this, event, callback._wrapped || callback, bubble);
}
Transmit error data to your backend
You can send error data using image tag as follows
function sendError(data) {
var img = newImage(),
src = 'http://yourserver.com/jserror&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.log('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
среда, 16 марта 2016 г.
Support ECMAScript 5, 6, 7 Shims and Shams
ECMAScript 5 (есть в es5-shim)
Object
- Object.keys
Array
- Array.isArray
- [].indexOf
- [].lastIndexOf
- [].every
- [].some
- [].forEach
- [].map
- [].filter
- [].reduce
- [].reduceRight
String
- "".trim
- "".split - crossbrowser (нет в es5-shim)
Function
- (function(){}).bind
Date
- Date.now
- (new Date()).toISOString
- (new Date()).toJSON
- (new Date()).parse -> return NaN for invalid dates
JSON (нет в es5-shim)
- JSON.parse
- JSON.stringify
ECMAScript 6 (есть в es6-shim)
Object
- Object.assign
- Object.is
Только, если есть поддержка ES5
- Object.getPrototypeOf
- Object.getOwnPropertyDescriptor
- Object.getOwnPropertyNames
- Object.seal
- Object.freeze
- Object.preventExtensions
- Object.isSealed
- Object.isExtensible
- Object.keys
String
- String.raw
- String.fromCodePoint
- "".codePointAt
- "".repeat
- "".startsWith
- "".endsWith
- "".includes
Number
- Number.isFinite
- Number.isInteger
- Number.isSafeInteger
- Number.isNaN
- Number.EPSILON
- Number.MIN_SAFE_INTEGER
- Number.MAX_SAFE_INTEGER
- Number('0o1')
- Number('0b1')
Array
- Array.from
- Array.of
- [].copyWithin
- [].find
- [].fineIndex
- [].fill
- [].keys
- [].values
- [].entries
RegExp
- (//).flags
Math
- Math.clz32
- Math.imul
- Math.sign
- Math.log10
- Math.log2
- Math.log1p
- Math.expm1
- Math.cosh
- Math.sinh
- Math.acosh
- Math.asinh
- Math.atanh
- Math.trunc
- Math.fround
- Math.cbrt
- Math.hypot
Map
Set
Reflect
Promise
ECMAScript 7 (есть в es7-shim)
Object
- Object.values
- Object.entries
- Object.getOwnPropertyDescriptors
Array
- [].includes
String
- "".padStart
- "".padEnd
- "".trimLeft
- "".trimRight
- "".at
Map
- (new Map()).toJSON
Set
- (new Set()).toJSON
Последовательность включения новых функций в проект:
- es5-shim.min.js
- es5-sham.min.js
- json3.min.js
- es6-shim.min.js
- es6-sham.min.js
- es7-shim.min.js
...other-libs.js...
Object
- Object.keys
Array
- Array.isArray
- [].indexOf
- [].lastIndexOf
- [].every
- [].some
- [].forEach
- [].map
- [].filter
- [].reduce
- [].reduceRight
String
- "".trim
- "".split - crossbrowser (нет в es5-shim)
Function
- (function(){}).bind
Date
- Date.now
- (new Date()).toISOString
- (new Date()).toJSON
- (new Date()).parse -> return NaN for invalid dates
JSON (нет в es5-shim)
- JSON.parse
- JSON.stringify
ECMAScript 6 (есть в es6-shim)
Object
- Object.assign
- Object.is
Только, если есть поддержка ES5
- Object.getPrototypeOf
- Object.getOwnPropertyDescriptor
- Object.getOwnPropertyNames
- Object.seal
- Object.freeze
- Object.preventExtensions
- Object.isSealed
- Object.isExtensible
- Object.keys
String
- String.raw
- String.fromCodePoint
- "".codePointAt
- "".repeat
- "".startsWith
- "".endsWith
- "".includes
Number
- Number.isFinite
- Number.isInteger
- Number.isSafeInteger
- Number.isNaN
- Number.EPSILON
- Number.MIN_SAFE_INTEGER
- Number.MAX_SAFE_INTEGER
- Number('0o1')
- Number('0b1')
Array
- Array.from
- Array.of
- [].copyWithin
- [].find
- [].fineIndex
- [].fill
- [].keys
- [].values
- [].entries
RegExp
- (//).flags
Math
- Math.clz32
- Math.imul
- Math.sign
- Math.log10
- Math.log2
- Math.log1p
- Math.expm1
- Math.cosh
- Math.sinh
- Math.acosh
- Math.asinh
- Math.atanh
- Math.trunc
- Math.fround
- Math.cbrt
- Math.hypot
Map
Set
Reflect
Promise
ECMAScript 7 (есть в es7-shim)
Object
- Object.values
- Object.entries
- Object.getOwnPropertyDescriptors
Array
- [].includes
String
- "".padStart
- "".padEnd
- "".trimLeft
- "".trimRight
- "".at
Map
- (new Map()).toJSON
Set
- (new Set()).toJSON
Последовательность включения новых функций в проект:
- es5-shim.min.js
- es5-sham.min.js
- json3.min.js
- es6-shim.min.js
- es6-sham.min.js
- es7-shim.min.js
...other-libs.js...
понедельник, 14 марта 2016 г.
JavaScript Decorator
function decorate (baseFunction, decoratorFunction) {
return function () {decoratorFunction(baseFunction, arguments);};
}
function a (a) {
console.log(a);
return 'OK';
}
function b (baseFunction, baseFunctionArguments) {
console.log('start');
baseFunction.apply(null, baseFunctionArguments);
console.log('b');
console.log('stop');
}
a = decorate(a, b);
a('a');
function trace (baseFunction, baseFunctionArguments) {
var result = baseFunction.apply(null, baseFunctionArguments);
console.log('TRACE: ' + baseFunction.name + ' (' + Array.prototype.slice.call(baseFunctionArguments).join(', ') + ') => ' + result);
return result;
}
var c = decorate(a, trace);
c('a', 'b', 1, 2, {});
return function () {decoratorFunction(baseFunction, arguments);};
}
function a (a) {
console.log(a);
return 'OK';
}
function b (baseFunction, baseFunctionArguments) {
console.log('start');
baseFunction.apply(null, baseFunctionArguments);
console.log('b');
console.log('stop');
}
a = decorate(a, b);
a('a');
function trace (baseFunction, baseFunctionArguments) {
var result = baseFunction.apply(null, baseFunctionArguments);
console.log('TRACE: ' + baseFunction.name + ' (' + Array.prototype.slice.call(baseFunctionArguments).join(', ') + ') => ' + result);
return result;
}
var c = decorate(a, trace);
c('a', 'b', 1, 2, {});
Подписаться на:
Сообщения (Atom)