(или как начать пользоваться уже сегодня)
(некоторые)
// Ошибка: `x` не определена
console.log(x);
let x;
// undefined
console.log(x);
if (true) {
let z = 3;
}
// Ошибка: `z` не определена
console.log(z);
let y = 1;
// Ошибка: `y` уже объявлена в текущей области видимости
let y = 2;
// Ошибка: `x` не определена
console.log(x);
const x = 0;
// Ошибка: объявление константы без значения
const y;
// Ошибка: попытка переопределения константы
y = 1;
// Двоичные
0b1001 === 9 // true
0B10010 === 18 // true
// Восьмеричные
0o755 === 493 // true
0O451 === 297 // true
// Шестнадцатеричные
0xFF === 255 // true
0X7C9D === 31901 // true
// Исправленные isNaN(), isFinite()
Number.isNaN(value)
Number.isFinite(value)
Number.MIN_SAFE_INTEGER // -2^53 + 1
Number.MAX_SAFE_INTEGER // 2^53 - 1
Number.isInteger(value)
Number.isSafeInteger(value)
Number.EPSILON // ≈ 2.22e-16
0.1 + 0.2 === 0.3 // false
0.3 - (0.1 + 0.2) < Number.EPSILON // true
var value = 42;
var obj = {
value: value,
getValue: function() {
return this.value;
}
};
obj['foo' + 'bar'] = value;
var value = 42;
var obj = {
value,
getValue() {
return this.value;
},
['foo' + 'bar']: value
};
// Исправленное ===
Object.is(NaN, NaN); // true
Object.is(-0, 0); // false
// Присваивает собственные перечисляемые свойства
Object.assign({
foo: 'foo'
}, { foo: 'bar'}, { foo: 'baz' }); // { foo: 'baz' }
// Использует геттеры
let bar = {
get foo() {
return 'bar';
}
};
Object.assign({}, foo); // { foo: 'bar' }
// И сеттеры
let baz = {
_foo: 'foo',
set foo(val) {
this._foo = val + 'baz';
}
};
Object.assign(baz, { foo: 'bar' }); // { _foo: 'barbaz', ... }
Аналогичны анонимным функциям с bind(this)
let empty = () => {};
let identify = x => x;
// Объект необходимо заворачивать в ()
let objectify = value => ({ key: value });
let squares = [1, 2, 3].map(x => x * x);
let odds = [1, 2, 3].filter(x => {
let isOdd = x % 2 === 0;
return isOdd;
});
this
привязан лексически, невозможно использовать в качестве конструктора||
function log(message) {
message = message || 'Default message';
console.log(message);
}
typeof
function substr(str, start, count) {
start = (typeof start !== 'undefined') ? start : 0;
count = (typeof count !== 'undefined') ?
count :
str.length - start;
return str.slice(start, end);
}
arguments
function substr(str, start, count) {
var len = arguments.length;
start = (len > 1) ? start : 0;
count = (len > 2) ? count : str.length - start;
return str.slice(start, end);
}
function log(message = 'Default message') {
console.log(message);
}
function substr(str, start = 0, count = str.length - start) {
return str.substr(start, count);
}
function f(head) {
var tail = Array.prototype.slice.call(arguments, f.length);
return tail;
}
function f(head, ...tail) {
return tail;
}
f(1, 2, 3); // [2, 3]
f(1); // []
function sum(...numbers) {
return numbers.reduce(function(memo, n) {
return memo + n;
});
}
console.log(sum(1, 2, 3, 4, 5)); // 15
Обычная рекурсия
function factorial(n) {
if (n === 0) return 1;
// Результат рекурсивного вызова модифицируется
return n * factorial(n - 1);
}
console.log(factorial(100000));
Стек вызовов
call factorial(3) // Фрэйм 1
call factorial(2) // Фрэйм 2
call factorial(1) // Фрэйм 3
call factorial(0) // Фрэйм 4 и т.д.
return 6
return 6
return 6
return 6
Хвостовая рекурсия
function tailFactorial(n, acc = 1) {
if (n === 0) return acc;
// Возвращается чистый вызов рекурсии
return tailFactorial(n - 1, n * acc);
}
// C оптимизацией хвостовой рекурсии ошибки не будет
console.log(tailFactorial(100000));
Стек вызовов
call tailFactorial(3, 1) // Фрэйм 1
replace args with (2, 3)
jump tailFactorial // Использовать фрэйм 1
replace args with (1, 6)
jump tailFactorial // Использовать фрэйм 1
replace args with (0, 6)
jump tailFactorial // Использовать фрэйм 1
String.prototype.repeat(value)
String.prototype.startsWith(value)
String.prototype.endsWith(value)
String.prototype.contains(value)
let evt = {
name: 'WSD',
desc: 'awesome'
};
console.log(`${evt.name} is ${evt.desc}`); // WSD is awesome
Многострочные литералы
let multiline = `This string is mutiline
actually`;
Сигнатура тега
function tag(strings, ...values) {
// Преобразует строки
// Преобразует значения
// Возвращает строку
}
// Использование
tag `Template literal`;
tag(strings, ...values);
Стандартный тег конкатенации
String.raw(strings, values1, ..., valueN)
Простой пример
function echo() {
return 'You shall not pass!';
}
let naive = echo `I'm the mighty string!`;
console.log(naive); // You shall not pass!
Полезный пример
function shoutify(strings, ...values) {
values = values.map(function(val) {
return val.toUpperCase();
});
return String.raw(strings, ...values);
}
let loudly = shoutify `You, ${'shall'} not ${'pass'}!`
console.log(loudly); // You, SHALL not PASS!
Array.of
// Произвольное число аргументов -> Массив
Array.of(element0, ..., elementN)
// Реализация с помощью rest параметров
Array.of = function(...args) {
return args;
};
Array.from
// arguments, NodeList -> Массив
Array.from(arrayLike, mapFn, thisArg)
function f() {
return Array.from(arguments);
}
f(1, 2, 3); // [1, 2, 3]
Array.from('1234'); // ['1', '2', '3', '4']
Array.from(document.querySelectorAll('div')); // [<div>, ...]
fill
Array.prototype.fill(value, start = 0, end = this.length)
let arr = [0, 0, 0].fill(1, 0, 3); // [1, 1, 1]
copyWithin
Array.prototype.copyWithin(targetStart, sourceStart, sourceEnd)
find
и findIndex
// Возвращает элемент либо undefined
Array.prototype.find(callback, thisArg])
// Возвращает индекс либо -1
Array.prototype.findIndex(callback, thisArg])
Вызовы функций
let arr = [1];
let missing = [2, 3, 4];
arr.push(...missing);
console.log(arr); // [1, 2, 3, 4];
Массивы
let missing = [2, 3];
let arr = [1, ...missing, 4];
console.log(arr); // [1, 2, 3, 4]
apply
для конструктора
let parts = [2014, 9, 26];
console.log(new Date(...parts));
Любое выражение после ...
console.log([1, ...'23'.split('').map(Number), 4]);
var arr = [1, 2, 3];
var first = arr[0];
var second = arr[1];
var third = arr[2];
let arr = [1, 2, 3];
let [first, second, third] = arr;
// Перестановка без дополнительной переменной
[second, first] = [first, second];
var nums = [1, 2, 3, 4, 5];
var head = nums[0];
var tail = nums.slice(1);
var fourth = nums[3];
let nums = [1, 2, 3, 4, 5];
let [head, ...tail] = nums;
// Можно игнорировать элементы
let [,,, fourth] = nums;
var M = [[1, 2], [3, 4]];
var m12 = M[0][1];
var m21 = M[1][0];
let M = [[1, 3], [2, 4]];
// Любая вложенность
let [, m12, [, m22]] = M;
var event = {
name: 'WSD',
desc: 'awesome'
};
var evtName = event.name;
var evtDesc = event.desc;
var name = event.name;
var desc = event.desc;
let event = {
name: 'WSD',
desc: 'awesome'
};
let {
name: evtName,
desc: evtDesc
} = event;
let { name, desc } = event;
var deep = {
arr: [
'first',
{ second: 'second' },
'third'
]
};
var second = deep.arr[1].second;
var third = deep.arr[2];
let deep = {
arr: [
'first',
{ second: 'second' },
'third'
]
};
let {
arr: [, { second }, third]
} = deep;
var missing = [][0]; // undefined
var found = missing || 1; // 1
let [missing] = []; // undefined
let [found = 1] = []; // 1
var missing = {}['missing']; // undefined
var found = missing || 1; // 1
let { missing } = {}; // undefined
let { found = 1 } = {}; // 1
Определение параметров функций
function ajax({ url, method = 'GET', callback = () => {} }) {
// Make a request
}
Множественные возвращаемые значения
function getDimensions() {
return { width: 10, height: 5 };
};
let { width: w, height: h } = getDimensions();
console.log(w, h); // 10 5
function getCoordinates() {
return [-10, 10];
};
let [x, y] = getCoordinates();
console.log(x, y) // -10 10
AMD — Require.js
CommonJS — Node.js, Browserify
utils.js
export default function (msg) {
console.log(msg);
};
main.js
import log from 'utils';
log('Hello, World!')
utils.js
export function logMessage(msg) {
console.log(msg);
}
function makeAssertion(expr, message) {
console.assert(expr, message);
}
export { logMessage as log, makeAssertion as assert };
math.js
export function isOdd(n) {
return n % 2 > 0;
}
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
// Экспорт по умолчанию также именованный
export { randomInt as default };
math.js
import { log, error } from 'utils';
// Импорт по умолчанию вместе с именованным
import random_int, { isOdd as is_odd } from 'math';
log(random_int(1, 5));
assert(is_odd(2), '2 это четное число!');
app.js
import { default as random_int } from 'math';
utils.js
export function log(msg) {
console.log(msg);
}
export function assert(msg) {
console.assert(expr, message);
}
main.js
import * as logger from 'logger';
logger.log('Hello, World!');
logger.assert(true === false, 'True это не false!')
System.import
, System.module
, System.set
, System.define
<module>
Изолированно:
С зависимостями:
for...of
Что используется сейчас:
let event = Ember.Object.create({
name: 'WSD',
desc: 'awesome'
});
event.get('name');
event.set('desc', 'super awesome');
Object.observe
Object.observe
let obj = {};
// Начать наблюдение
Object.observe(obj, function(changes) {
changes.forEach(function({ type, name, oldValue }) {
console.log(type, name, oldValue);
});
});
// Оставить в покое
Object.unobserve(obj);
Можно наблюдать только интересующие изменения
let obj = {};
let interest = ['add', 'update', 'delete'];
// Начать наблюдение
Object.observe(obj, (changes) => {
// Использовать изменения
}, interest);
Пользовательские события
let obj = {
_foo: 'foo',
set foo(value) {
let event = {
type: 'special-event',
name: 'set-value',
oldValue: this._foo,
value: value
};
Object.getNotifier(this).notify(event);
}
};
Пользовательские события
let interest = ['special-event'];
Object.observe(obj, (changes) => {
console.log(changes[0]);
}, interest);
obj.foo = 'bar';
--harmony
)Можно искать по запросу es7 strawman
И следить на esdiscuss.org
* с флагом --enable-javascript-harmony
50 / 101 c флагом --harmony
Плюсы:
Минусы:
Плюсы:
Минусы:
Где не стоит:
Где можно и нужно: