ШРИ - JavaScript базовые знания

ШРИ - JavaScript базовые знания

В лекции подробно рассмотрены тонкие моменты языка JavaScript, с которыми часто возникают основные проблемы. Наглядные примеры и рецепты помогают лучше понять его особенности.

Video https://events.yandex.ru/lib/talks/704/

B827d6cfdfbcfce33700b0e6cc03e344?s=128

Mikhail Davydov

October 11, 2012
Tweet

Transcript

  1. 1.
  2. 4.

    4 Statement •  Блочное выражение –  if (){}, try{}catch(e){}, function

    a(){} •  Директива интерпретатору –  return, throw, break, continue, var, … •  Может включать другие блочные выражения •  Может включать выражения •  Не возвращает значение •  Не может быть аргументом Expression •  Можно сделать из Expression – Expression; http://es5.github.com/#x12
  3. 5.

    5 Expression •  Оператор –  С одним аргументом typeof, !,

    (), ++, --, new, +,… –  С двумя ==, ===, >, <, instanceof, +, -,… –  С тремя a?b:c,… –  Вызов функции –  Оператор запятая •  Может включать другие операторы •  Не может включать Statement •  Возвращает значение •  Может быть в составе Statement http://es5.github.com/#x11
  4. 7.

    7 Приведение типов •  Зависит от оператора –  Оператор имеет

    определенный алгоритм •  Зависит от типа аргументов и мест •  Внутренние функции JavaScript –  ToNumber, ToString, ToBoolean, ToObject
  5. 8.

    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); } http://es5.github.com/#x11.6.1
  6. 10.

    10 Применяется тот же алгоритм Вся «магия» в ToString({}) “2”

    + {}; // ”2[object Object]” Пример: оператор + объект if (IsCallable({}.toString)) { return ({}).toString(); } else if (IsCallable({}.valueOf)) { return ({}). valueOf(); } else { throw new TypeError(); } Concat(ToString(“2”), ToString({})); ToString({}) -> ToPrimitive({}, “String”) ToPrimitive({}, “String”) -> ({}).[[DefaultValue]](“String”) http://es5.github.com/#x8.12.8
  7. 12.

    12 The Abstract Equality Comparison Algorithm http://es5.github.com/#x11.9.3 '' === '0'

    // false! 0 === '' // false! 0 === '0' // false! false === undefined // false! false === null // false! null === undefined // false! +0 === -0 // true! Операторы == и === '' == '0' // false 0 == '' // true 0 == '0' // true false == undefined // false false == null // false null == undefined // true The Strict Equality Comparison Algorithm http://es5.github.com/#x11.9.6
  8. 13.

    13 Оператор typeof Type(val) Результат Undefined "undefined" Null "object" Boolean

    "boolean" Number "number" String "string" Object (нативный и не имеет [[Call]]) "object" Object (нативный или не нативный и имеет [[Call]]) "function” Object (не нативный и не имеет [[Call]]) Не "undefined", "boolean", "number", "string" http://es5.github.com/#x11.4.3 Алгоритм - Ссылка не достижима (IsUnresolvableReference) – возвращаем "undefined" - Иначе смотрим по таблице
  9. 14.

    14 WAT? •  [1] > 0; // ? •  [1,1]

    > 0; // ? •  [1,] > 0; // ? •  [1,,] > 0; // ? •  [1] > "0"; // ?
  10. 15.

    15 WAT? •  [1] > 0; // true •  [1,1]

    > 0; // false •  [1,] > 0; // true •  [1,,] > 0; // false •  [1] > "0"; // ?
  11. 17.

    17 На самом деле Function в JavaScript – это Object

    со скрытым полем [[Call]] http://es5.github.com/#x13.2
  12. 18.

    18 - Это Statement - Инициализируется во время входа в

    контекст - Объявляется в блоке функции или в глобальном блоке a(); // OK function a() { b(); // OK function b() { } } a(); Function Declaration/Definition http://es5.github.com/#x13
  13. 19.

    19 - Это тоже Statement - Инициализируется во время входа

    в контекст или в рантайме - По стандарту такая запись недопустима if (true) { function a() { return 1; } } else { function a() { return 2; } } a(); // Firefox – 1, Others - 2 Conditional Function Declaration
  14. 20.

    20 - При использовании строгого режима возникнет ошибка SyntaxError "use

    strict"; if (true) { function a() { return 1; } } else { function a() { return 2; } } // SyntaxError // Function Expression! CFD+Strict Mode
  15. 21.

    21 - Это expression - Инициализируется в рантайме - Объявляется

    где угодно a(); // error var a = function () { b(); // error var b = function () { }; b(); // ok }; a(); // ok Function Expression http://es5.github.com/#x11.2.5
  16. 22.

    22 - Это тот же Function Expression - Можно обратиться

    к себе по своему имени - Имя доступно только в своем блоке (кроме старых IE) (function timer() { setTimeout(timer, 1000); console.log(+new Date); }()); typeof timer; // undefined, Old IE - function Named Function Expression
  17. 23.

    23 - Это тот же 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 IEFE
  18. 24.

    Область видимости Определяется во время создания функции Не меняется при

    передаче функции Образует цепочку областей видимости Лексическая Образует «замыкание»
  19. 25.

    25 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 http://es5.github.com/#x10.2
  20. 27.

    Вызов функции и this this – основная грабля в JavaScript

    Прямой вызов Вызов через c оператором точка и [] Вызов через new Вызов через call, apply, bind
  21. 29.

    29 () – это оператор вызова функции this всегда undefined

    но он трансформируется в global В строгом режиме всегда undefined (трансформации нет) function a() { console.log(this); } a(); // window (undefined -> window) function b() { “use strict”; console.log(this); } b(); // undefined Прямой вызов – через оператор ()
  22. 30.

    30 Это 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(); // ??? Оператор . и [] http://es5.github.com/#x11.2.1
  23. 31.

    31 Это Expression new – это еще один способ вызова

    функции Каждая функция может быть конструктором this – пустой объект со ссылкой на prototype вызываемой функции var A = function () { console.log(this); console.log(this.__proto__ === A.prototype); }; new A(); // Object, true Оператор new http://es5.github.com/#x11.2.2
  24. 32.

    32 Это способ управлять значением this this – объект, который

    вы передаете var a = function (a, b) { console.log(this, a, b); }; a.call([]); // [], undefined, undefined a.call([], 1, 2); // [], 1, 2 a.apply([], [1, 2]); // [], 1, 2 Call, apply http://es5.github.com/#x15.3.4.4 http://es5.github.com/#x15.3.4.3
  25. 33.

    33 Это способ подменять this без вызова функции this –

    объект, который вы передаете var a = function () { console.log(this); }; var b = a.bind({}); b(); // {} Bind http://es5.github.com/#x15.3.4.5 MDN Function#bind http://clck.ru/2EeTx
  26. 35.

    35 Передача значения в функцию •  Значения передаются по ссылке

    •  Можно менять «поля» переданного объекта •  Примитив менять нельзя •  Можно переписать ссылку без потери объекта
  27. 36.

    36 arguments •  Как и this появляется при вызове • 

    Это не Array •  Содержит список всех аргументов –  arguments[0]… •  Содержит ссылку на вызывающий конекст –  arguments.caller –  Deprecated! •  Содержит ссылку на себя –  arguments.calle http://es5.github.com/#x10.6
  28. 38.

    38 prototype и __proto__ •  prototype – свойство функции – 

    Оно есть у функции с рождения –  По умолчанию это пустой объект •  __proto__ – ссылка на prototype у объекта –  Во многих движках JavaScript оно скрыто –  Определяется во время работы оператора new http://es5.github.com/#x15.3.5.2 http://es5.github.com/#x8.6.2
  29. 39.

    39 var Foo = function () { this.b = 146;

    // Собственное свойство }; Foo.prototype.bar = function () { console.log(this); }; Foo.prototype.a = 123; var foo = new Foo(); foo.bar(); // foo foo.a; // 123 foo['b']; // 146 foo.c; // undefined Foo.prototype.c = 8; foo.c; // 8 <- Magic??? Цепочка прототипов
  30. 40.

    40 Цепочка прототипов foo b 146 __proto__ object Foo.prototype bar

    function a 123 __proto__ object Object.prototype __proto__ null http://es5.github.com/#x4.2.1
  31. 41.

    41 Оператор . и [] •  Выполняет поиск свойства • 

    Использует цепочку прототипов •  Ищет в собственных свойствах •  Затем рекурсивно по ссылке __proto__ •  Если __proto__ null – возвратит undefined http://es5.github.com/#x11.2.1
  32. 42.

    42 var Foo = function () { this.b = 146;

    }; var foo = new Foo(); foo instanceof Foo; // true foo instanceof Object; // true <- Магия?? foo instanceof Array; // false Оператор instanceof http://es5.github.com/#x11.8.6
  33. 44.

    44 Цепочка прототипов foo b 146 __proto__ object Foo.prototype bar

    function a 123 __proto__ object Object.prototype __proto__ null
  34. 46.

    Strict Mode На самоподготовку - выделите отличия от обычного режима

    - всегда ли стоит применять Strict Mode? - в каком месте кода стоит объявлять SM? http://es5.github.com/#x10.1.1