В лекции подробно рассмотрены тонкие моменты языка JavaScript, с которыми часто возникают основные проблемы. Наглядные примеры и рецепты помогают лучше понять его особенности.
4. Statement
• Блочное выражение
– if (){}, try{}catch(e){}, function a(){}
• Директива интерпретатору
– return, throw, break, continue, var, …
• Может включать другие блочные выражения
• Может включать выражения
• Не возвращает значение
• Не может быть аргументом Expression
• Можно сделать из Expression – Expression;
4
http://es5.github.com/#x12
5. Expression
• Оператор
– С одним аргументом typeof, !, (), ++, --, new, +,…
– С двумя ==, ===, >, <, instanceof, +, -,…
– С тремя a?b:c,…
– Вызов функции
– Оператор запятая
• Может включать другие операторы
• Не может включать Statement
• Возвращает значение
• Может быть в составе Statement
5
http://es5.github.com/#x11
7. Приведение типов
• Зависит от оператора
– Оператор имеет определенный алгоритм
• Зависит от типа аргументов и мест
• Внутренние функции JavaScript
– ToNumber, ToString, ToBoolean, ToObject
7
8. Пример: оператор + и примитивы
Сильно перегружен: сложение чисел, конкатенация строк
"2" + 3; // "23"
2 + 3; // 5
// Что происходит в внутренностях JavaScript
if (Type("2") === "String" ||
Type(3) === "String") {
return Concat(ToString("2"), ToString(3));
} else {
return ToNumber(2) + ToNumber(3);
}
8 http://es5.github.com/#x11.6.1
10. Пример: оператор + объект
Применяется тот же алгоритм
Вся «магия» в ToString({})
"2" + {}; // "2[object Object]"
Concat(ToString("2"), ToString({}));
ToString({}) ->
ToPrimitive({}, "String")
ToPrimitive({}, "String") ->
({}).[[DefaultValue]]("String")
10 http://es5.github.com/#x8.12.8
11. Пример: оператор + объект
Применяется тот же алгоритм
Вся «магия» в ToString({})
if (IsCallable({}.toString)) {
return ({}).toString();
} else if (IsCallable({}.valueOf)) {
return ({}). valueOf();
} else {
throw new TypeError();
}
11 http://es5.github.com/#x8.12.8
18. Функции
Function Declaration,
Conditional Function Declaration,
Function Expression,
Named Function Expression,
IEFE
19. На самом деле Function в
JavaScript – это Object со
скрытым полем [[Call]]
19 http://es5.github.com/#x13.2
20. Function Declaration/Definition
- Это Statement
- Инициализируется во время входа в контекст
- Объявляется в блоке функции или в глобальном блоке
a(); // OK
function a() {
b(); // OK
function b() {
}
}
a();
20
http://es5.github.com/#x13
21. Conditional Function Declaration
- Это тоже Statement
- Инициализируется во время входа в контекст или в рантайме
- По стандарту такая запись недопустима
if (true) {
function a() {
return 1;
}
} else {
function a() {
return 2;
}
}
a(); // Firefox – 1, Others - 2
21
22. CFD+Strict Mode
- При использовании строгого режима тут будет SyntaxError
"use strict";
if (true) {
function a() {
return 1;
}
} else {
function a() {
return 2;
}
}
// SyntaxError
// Use Function Expression!
22
23. Function Expression
- Это expression
- Инициализируется в рантайме
- Объявляется где угодно
a(); // error
var a = function () {
b(); // error
var b = function () {};
b(); // ok
};
a(); // ok
23
http://es5.github.com/#x11.2.5
24. Named Function Expression
- Это тот же Function Expression
- Можно обратиться к себе по своему имени
- Имя доступно только в своем блоке (кроме старых IE)
(function timer() {
setTimeout(timer, 1000);
console.log(+new Date);
}());
typeof timer; // undefined, Old IE -
function
24
25. IEFE
- Это тот же Function Expression
- Мы даем понять интерпретатору, что этот код - Function Expression
- IEFE позволяет эмулировать блочную область видимости
function (){}(); // SyntaxError
!function (){}(); // OK
+function (){}(); // OK
*function (){}(); // OK
(function (){}()); // OK
[function (){}()]; // OK
var a = function (){}();
var a = (function (){}()); // The best
25
26. Область видимости
Определяется во время создания функции
Не меняется при передаче функции
Образует цепочку областей видимости
Лексическая
Образует «замыкание»
27. Область видимости
var a = 1;
function foo() {
var c = 2;
function bar(e) {
return a + c + e;
}
return bar(3);
}
foo(); // 6
http://es5.github.com/#x10.3
27 http://es5.github.com/#x10.2
29. Вызов функции и this
this – основная грабля в JavaScript
Прямой вызов
Вызов через c оператором точка и []
Вызов через new
Вызов через call, apply, bind
30. This в JavaScript
определяется во время
вызова функции!
30 http://es5.github.com/#x11.2.3
31. Прямой вызов – через оператор ()
() – это оператор вызова функции
this всегда undefined но он трансформируется в global
В строгом режиме всегда undefined (трансформации нет)
function a() {
console.log(this);
}
a(); // window (undefined -> window)
function b() {
"use strict";
console.log(this);
}
b(); // undefined
31
32. Вызов функции и оператор . и []
Это Expression
this – объект от которого был получена эта функция
var foo = {
bar: function () {
console.log(this);
}
};
foo.bar(); // foo
var baz = {};
baz.bar = foo.bar;
baz.bar(); // baz
var fooBar = foo.bar;
fooBar(); // ???
32 http://es5.github.com/#x11.2.1
33. Оператор new
Это Expression
new – это еще один способ вызова функции
Каждая функция может быть конструктором
this – пустой объект со ссылкой на prototype вызываемой функции
var A = function () {
console.log(this);
console.log(
this.__proto__ === A.prototype
);
};
new A(); // Object, true
33 http://es5.github.com/#x11.2.2
34. Call, apply
Это способ управлять значением this
this – объект, который вы передаете
var a = function (a, b) {
console.log(this, a, b);
};
a.call([]); // [], undefined, …
a.call([], 1, 2); // [], 1, 2
a.apply([], [1, 2]); // [], 1, 2
http://es5.github.com/#x15.3.4.4
34 http://es5.github.com/#x15.3.4.3
35. Bind
Это способ подменять this без вызова функции
this – объект, который вы передаете
var a = function () {
console.log(this);
};
var b = a.bind({});
b(); // {}
http://es5.github.com/#x15.3.4.5
35 MDN Function#bind http://clck.ru/2EeTx
37. Передача значения в функцию
• Значения передаются по ссылке
• Можно менять «поля» переданного объекта
• Примитив менять нельзя
• Можно переписать ссылку без потери
объекта
37
38. arguments
• Как и this появляется при вызове
• Это не Array
• Содержит список всех аргументов
– arguments[0]…
• Содержит ссылку на вызывающий конекст
– arguments.caller
– Deprecated!
• Содержит ссылку на себя
– arguments.calle
38 http://es5.github.com/#x10.6
40. prototype и __proto__
• prototype – свойство функции
– Оно есть у функции с рождения
– По умолчанию это пустой объект
• __proto__ – ссылка на prototype у объекта
– Во многих движках JavaScript оно скрыто
– Определяется во время работы оператора new
http://es5.github.com/#x15.3.5.2
40
http://es5.github.com/#x8.6.2
41. Цепочка прототипов
var Foo = function () {
// Собственное свойство
this.b = 146;
};
Foo.prototype.bar = function () {
console.log(this);
};
Foo.prototype.a = 123;
41
43. Цепочка прототипов
foo
b 146
__proto__ object
Foo.prototype
bar function
a 123
__proto__ object
Object.prototype
__proto__ null
43
http://es5.github.com/#x4.2.1
44. Оператор . и []
• Выполняет поиск свойства
• Использует цепочку прототипов
• Ищет в собственных свойствах
• Затем рекурсивно по ссылке __proto__
• Если __proto__ null – возвратит undefined
44 http://es5.github.com/#x11.2.1
45. Оператор instanceof
var Foo = function () {
this.b = 146;
};
var foo = new Foo();
foo instanceof Foo; // true
foo instanceof Object; // true Магия??
foo instanceof Array; // false
45 http://es5.github.com/#x11.8.6
49. Strict Mode
На самоподготовку
- выделите отличия от обычного режима
- всегда ли стоит применять Strict Mode?
- в каком месте кода стоит объявлять SM?
http://es5.github.com/#x10.1.1