var x = 'outer';
function test(inner) {
if (inner) {
var x = 'inner'; // scope whole function
return x;
}
return x; // gets redefined on line 4
}
test(false); // undefined
test(true); // inner
let x = 'outer';
function test(inner) {
if (inner) {
let x = 'inner';
return x;
}
return x; // gets result from line 1 as expected
}
test(false); // outer
test(true); // inner
(function(){
var private2 = 1;
})();
console.log(private2); // Uncaught ReferenceError
{
let private3 = 1;
}
console.log(private3); // Uncaught ReferenceError
IIFE используется для содержания глобальной среды в чистоте
Достаточно использовать блоки и let
{
const ARR = [5, 6];
ARR.push(7);
console.log(ARR); // [5,6,7]
ARR = 10; // TypeError
ARR[0] = 3; // значение можно менять
console.log(ARR); // [3,6,7]
}
Другой формой объявления переменной с блочной областью видимости является ключевое слово const. Оно предназначено для объявления переменных (констант), значения которых доступны только для чтения. Это означает не то, что значение константы неизменно, а то, что идентификатор переменной не может быть переприсвоен.
function Person() {
var self = this;
self.age = 0;
setInterval(function growUp() {
// Коллбэк относится к переменной `self`,
// значением которой является
// ожидаемый объект.
self.age++;
}, 1000);
}
function Person() {
this.age = 0;
setInterval(() => {
this.age++;
// `this` относится к объекту person
}, 1000);
}
var p = new Person();
ES5
ES6
Каждая функция в JavaScript определяет свой собственный контекст this
внутри стрелочных функций значение this то же самое, что и снаружи
var _this = this; // need to hold a reference
$('.btn').click(function(event){
_this.sendData(); // reference outer this
});
$('.input').on('change',function(event){
this.sendData(); // reference outer this
}.bind(this)); // bind to outer this
// this will reference the outer one
$('.btn').click((event) =>
this.sendData());
// implicit returns
const ids = [291, 288, 984];
const messages = ids.map(value =>
`ID is ${value}`);
ES5
ES6
let getFinalPrice = (price, tax = 0.7) => price + price * tax;
getFinalPrice(500); // 850, так как значение tax не задано
getFinalPrice(500, 0.2); // 600, значение tax по-умолчанию
// заменяется на 0.2
ES5
function point(x, y, isFlag){
x = x || 0;
y = y || -1;
isFlag = isFlag || true;
console.log(x,y, isFlag);
}
point(0, 0) // 0 -1 true
point(0, 0, false) // 0 -1 true
point(1) // 1 -1 true
point() // 0 -1 true
ES6
function point(x = 0, y = -1, isFlag = true){
console.log(x,y, isFlag);
}
point(0, 0) // 0 0 true
point(0, 0, false) // 0 0 false
point(1) // 1 -1 true
point() // 0 -1 true
Spread
function foo(x, y, z) {
console.log(x, y, z);
}
let arr = [1, 2, 3];
foo(...arr); // 1 2 3
Rest
function foo(...args) {
console.log(args);
}
foo(1, 2, 3, 4, 5); // [1, 2, 3, 4, 5]
function getCar(make, model, value) {
return {
// с синтаксисом короткой записи можно пропускать значение свойства, если оно
// совпадает с именем переменной, значение которой мы хотим использовать
make, // аналогично make: make
model, // аналогично model: model
value, // аналогично value: value
// вычисляемые свойства теперь работают в литералах объекта
['make' + make]: true,
// Короткая запись метода объекта пропускает ключевое слово `function` и двоеточие.
// Вместо "depreciate: function() {}" можно написать:
depreciate() {
this.value -= 2500;
}
};
}
let car = getCar('Kia', 'Sorento', 40000);
console.log(car);
// {
// make: 'Kia',
// model:'Sorento',
// value: 40000,
// makeKia: true,
// depreciate: function()
// }
Text
Получение элемента из массива
ES5
var array = [1, 2, 3, 4];
var first = array[0];
var third = array[2];
console.log(first, third); // 1 3
ES6
const array = [1, 2, 3, 4];
const [first, ,third] = array;
console.log(first, third); // 1 3
Обмен значениями
Text
ES5
var a = 1;
var b = 2;
var tmp = a;
a = b;
b = tmp;
console.log(a, b); // 2 1
ES6
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b); // 2 1
Text
Деструктуризация нескольких возвращаемых значений
ES5
function margin() {
var left=1, right=2,
top=3, bottom=4;
return {
left: left,
right: right,
top: top,
bottom: bottom
};
}
var data = margin();
var left = data.left;
var bottom = data.bottom;
console.log(left, bottom); // 1 4
ES6
function margin() {
const left=1, right=2,
top=3, bottom=4;
return { left, right, top, bottom };
}
const { left, bottom } = margin();
console.log(left, bottom); // 1 4
С ES6 вызывающий код выбирает только нужные данные
Text
Деструктуризация и сопоставление параметров
ES5
var user = {
firstName: 'Adrian',
lastName: 'Mejia'};
function getFullName(user) {
var firstName = user.firstName;
var lastName = user.lastName;
return firstName + ' ' + lastName;
}
console.log(getFullName(user));
// Adrian Mejia
ES6
const user = {
firstName: 'Adrian',
lastName: 'Mejia'};
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
console.log(getFullName(user)); // Adrian Mejia
Text
Глубокое сопоставление (деструктуризация объекта )
ES5
function settings() {
return { display: { color: 'red' }, keyboard: { layout: 'querty'} };
}
var tmp = settings();
var displayColor = tmp.display.color;
var keyboardLayout = tmp.keyboard.layout;
console.log(displayColor, keyboardLayout);
// red querty
ES6
function settings() {
return { display: { color: 'red' }, keyboard: { layout: 'querty'} };
}
const { display: { color: displayColor }, keyboard: { layout: keyboardLayout }} = settings();
console.log(displayColor, keyboardLayout); // red querty
Советы:
Text
Каждый объект в JavaScript имеет прототип, который является другим объектом. Все объекты в JavaScript наследуют методы и свойства от своего прототипа.
ES5
var Animal = (function () {
function MyConstructor(name) {
this.name = name;
}
MyConstructor.prototype.speak = function speak() {
console.log(this.name + ' makes a noise.');
};
return MyConstructor;
})();
var animal = new Animal('animal');
animal.speak(); // animal makes a noise.
ES6
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
const animal = new Animal('animal');
animal.speak(); // animal makes a noise.
Text
Советы:
О чём стоит помнить:
Text
ES5
var Lion = (function () {
function MyConstructor(name){
Animal.call(this, name);
}
// prototypal inheritance
MyConstructor.prototype = Object.create(Animal.prototype);
MyConstructor.prototype.constructor = Animal;
MyConstructor.prototype.speak = function speak() {
Animal.prototype.speak.call(this);
console.log(this.name + ' roars ');
};
return MyConstructor;
})();
var lion = new Lion('Simba');
lion.speak(); // Simba makes a noise.
// Simba roars.
ES6
class Lion extends Animal {
speak() {
super.speak();
console.log(this.name + ' roars ');
}
}
const lion = new Lion('Simba');
lion.speak(); // Simba makes a noise.
// Simba roars.
Text
ES5
function printAfterTimeout(string, timeout, done){
setTimeout(function(){
done(string);
}, timeout);
}
printAfterTimeout('Hello ', 1000, function(result){
console.log(result);
// nested callback
printAfterTimeout(result + 'Reader', 1000, function(result){
console.log(result);
});
});
ES6
function printAfterTimeout(string, timeout){
return new Promise((resolve, reject) => {
setTimeout(function(){
resolve(string);
}, timeout);
});
}
printAfterTimeout('Hello ', 1000).then((result) => {
console.log(result);
return printAfterTimeout(result + 'Reader', 1000);
}).then((result) => {
console.log(result);
});
Text
function *infiniteNumbers() {
var n = 1;
while (true) {
yield n++;
}
}
var numbers = infiniteNumbers(); // возвращает перебираемый объект
numbers.next(); // { value: 1, done: false }
numbers.next(); // { value: 2, done: false }
numbers.next(); // { value: 3, done: false }
Функции-генераторы представляют собой новую особенность ES6, которая позволяет функции создавать много значений в течение некоторого периода времени, возвращая объект (называемый генератором), который может быть итерирован для выброса значений из функции по одному за раз.
Text
Целью Symbol является создание уникального идентификатора, к которому нельзя получить доступ.
var sym = Symbol("опциональное описание");
console.log(typeof sym); // symbol
var o = {
val: 10,
[Symbol("случайный")]: "Я - символ",
};
console.log(Object.getOwnPropertyNames(o));
// val
использовать new вместе с Symbol(…) нельзя.
Если Symbol используется как свойство/ключ объекта, он сохраняется таким специальным образом, что свойство не будет показано при нормальном перечислении свойств объекта.
Чтобы извлечь символьные свойства объекта, нужно использовать Object.getOwnPropertySymbols(o)