Upload
mikhail-davydov
View
236
Download
2
Tags:
Embed Size (px)
Citation preview
Михаил Давыдов Разработчик JavaScript
JavaScript Циклы и Функции
Циклы – Statements
for,
while,
do while,
for in
for, while, do while – работают так же как и во всех языках. Ура!
for in
• Можно итерировать поля объекта • Пробегает по перечисляемым свойствам
– По собственным свойствам – И по свойствам прототипа
• Перечисляемость – скрытое свойство
6
var obj = { a: 1, b: {}, c: 'ololo' }; for (var keyName in obj) { console.log(keyName + ': ' + obj[keyName]); } // Результат "a: 1" "b: [object Object]" "c: 'ololo'" typeof obj.toString === "function"; // Почему его нет? typeof obj.hasOwnProperty === "function"; // Почему его нет?
for in: Пример
7
hasOwnProperty и toString и др. – не перечисляемые свойства
8
// А что если? Object.prototype.toString = function () {};
9
Если toString и другие переписать, то они станут уже перечисляемыми
10
var Constructor = function () {}; Constructor.prototype.myValue = 123; var obj = new Constructor(); obj.a = 1; obj.b = {}; obj.c = 'ololo'; for (var keyName in obj) { console.log(keyName + ': ' + obj[keyName]); } // Результат "a: 1" "b: [object Object]" "c: 'ololo'" "myValue: 123" // <<< ????
for in: Пример с загрязнением
11
myValue – перечисляемое, но не собственное свойство
12
var Constructor = function () {}; Constructor.prototype.myValue = 123; var obj = new Constructor(); obj.a = 1; obj.b = {}; obj.c = 'ololo'; for (var keyName in obj) { if (obj.hasOwnProperty(keyName)) { console.log(keyName + ': ' + obj[keyName]); } } // Результат "a: 1" "b: [object Object]" "c: 'ololo'"
for in: Пример c hasOwnProperty
Циклы Expressions
forEach
map
every, some
filter
reduce, reduceRight
Как правило все циклы связаны с массивом
Почему бы тогда не добавить итераторов к Array?!
var persons = [{ "name": "Ann", "age": 21 }, { "name": "Helen", "age": 16 }, { "name": "Peter", "age": 76 }, { "name": "Jack", "age": 12 }];
Пример
persons.forEach(): Undefined
// Слишком много шума и лишних слов for (var i = 0; i < persons.length; i++) { console.log(persons[i].name[0]); } // "A", "H", "P", "J" // Лучше, чище, нагляднее persons.forEach(function (person) { console.log(person.name[0]); }); // "A", "H", "P", "J"
forEach(): вывести 1 букву имени
persons.map(): Array
var result = []; // Слишком много шума и лишних слов for (var i = 0; i < persons.length; i++) { result.push(persons[i].name); } console.log(result); // ["Ann", "Helen", "Peter", "Jack"] // Лучше, чище, нагляднее var result = persons.map(function (person) { return person.name; }); console.log(result); // ["Ann", "Helen", "Peter", "Jack"]
map(): получить только имена
persons.some(): Boolean
var isPensioners = false; // Слишком много шума и лишних слов for (var i = 0; i < persons.length; i++) { if (persons[i].age > 65) { isPensioners = true; break; } } console.log(isPensioners); // true // Лучше, чище, нагляднее var isPensioners = persons.some(function (person) { return person.age > 65; }); console.log(isPensioners); // true
some(): есть ли пенсионеры?
persons.every(): Boolean
var isAllAdults = true; // Слишком много шума и лишних слов for (var i = 0; i < persons.length; i++) { if (persons[i].age < 18) { isAllAdults = false; break; } } console.log(isAllAdults); // false // Лучше, чище, нагляднее var isAllAdults = persons.every(function (person) { return person.age >= 18; }); console.log(isAllAdults); // false
every(): все совершеннолетние?
persons.filter(): Array
var underages = []; // Слишком много шума и лишних слов for (var i = 0; i < persons.length; i++) { if (persons[i].age < 18) { underages.push(persons[i]); } } console.log(underages.length); // 1 // Лучше, чище, нагляднее var underages = persons.filter(function (person) { return person.age < 18; }); console.log(underages.length); // 1
filter(): список несовершеннолетних
persons.reduce(): *
var ageSumm = 0; // Слишком много шума и лишних слов for (var i = 0; i < persons.length; i++) { ageSumm += persons[i].age; } console.log(ageSumm / persons.length); // 20.5 // Лучше, чище, нагляднее var underages = persons.reduce(function (prev, current) { return prev + current.age; }, 0); // 0 - Аккумулятор console.log(ageSumm / persons.length); // 20.5
reduce(): средний возраст
Цепочки вызовов persons.filter().map().join()
var adultNames = persons // Сперва выбираем всех совершеннолетник .filter(function (person) { return person.age >= 18; }) // Затем оставляем только имена .map(function (person) { return person.name; }) // Склеиваем имена в строку .join(', '); console.log(adultNames + ' are adults'); // Ann, Peter are adults
Получить имена совершеннолетних
Внимание все они не поддерживаются старыми браузерами!
5+ 3+ 10+ 3.2+ 9+
Функции
Function Declaration,
Conditional Function Declaration,
Function Expression,
Named Function Expression,
IEFE
33
На самом деле Function в JavaScript – это Object со скрытым полем [[Call]]
http://es5.github.com/#x13.2
34
- Это Statement - Инициализируется во время входа в контекст - Объявляется в блоке функции или в глобальном блоке
a(); // OK function a() { b(); // OK function b() { } } a();
Function Declaration/Definition
http://es5.github.com/#x13
35
- Это тоже Statement - Инициализируется во время входа в контекст или в рантайме - По стандарту такая запись недопустима
if (true) { function a() { return 1; } } else { function a() { return 2; } } a(); // Firefox – 1, Others - 2
Conditional Function Declaration
36
- При использовании строгого режима возникнет ошибка SyntaxError
"use strict"; if (true) { function a() { return 1; } } else { function a() { return 2; } } // SyntaxError // Function Expression!
CFD+Strict Mode
37
- Это expression - Инициализируется в рантайме - Объявляется где угодно
a(); // error var a = function () { b(); // error var b = function () { }; b(); // ok }; a(); // ok
Function Expression
http://es5.github.com/#x11.2.5
38
- Это тот же Function Expression - Можно обратиться к себе по своему имени - Имя доступно только в своем блоке (кроме старых IE)
(function timer() { setTimeout(timer, 1000); console.log(+new Date); }()); typeof timer; // undefined, Old IE - function
Named Function Expression
39
- Это тот же Function Expression - Мы даем понять интерпретатору, что этот код - Function Expression - IEFE позволяет эмулировать блочную область видимости
function (){}(); // SyntaxError (function () { // OK var b = Math.sin(Math.PI / 3); alert(b * 2); }()); typeof b === "undefined";
IEFE – Замыкание, Модуль
40
!function (){}(); // OK +function (){}(); // OK *function (){}(); // OK (function (){}()); // OK [function (){}()]; // OK var a = function (){}(); // Можно и так var a = (function (){}()); // Но лучше скобки оставлять
IEFE
Область видимости
Определяется во время создания функции
Не меняется при передаче функции
Образует цепочку областей видимости
Лексическая
Образует «замыкание»
42
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
43
Цепочка областей видимости
GLOBAL a 1 foo func(on
foo c 2 bar func(on
bar e argument
44
Вся эта цепочка остается в памяти, пока жива функция bar()
45
// Замыкание var getMySecret = (function () { // Это значение нельзя изменить var mySecret = Math.sin(Math.PI / 3); return function () { return mySecret; }; }()); // Можем только получать getMySecret(); // 0.8660254037844386 typeof mySecret === "undefined";
Пример области видимости
Вызов функции и this
this – основная грабля в JavaScript
Прямой вызов
Вызов через c оператором точка и []
Вызов через new
Вызов через call, apply, bind
47
This в JavaScript определяется во время вызова функции!
http://es5.github.com/#x11.2.3
48
() – это оператор вызова функции this всегда undefined но он трансформируется в global В строгом режиме всегда undefined (трансформации нет)
function a() { console.log(this); } a(); // window (undefined -> window) function b() { "use strict"; console.log(this); } b(); // undefined
Прямой вызов – через оператор ()
49
Это 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
50
Легко запомнить: что находится до "точки" является this
51
Это 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
52
Это способ управлять значением 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
53
Это способ подменять 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
Вызов функции: arguments
Передача значения
arguments
55
Передача значения в функцию
• Значения передаются по ссылке • Можно менять «поля» переданного объекта • Примитив менять нельзя • Можно переписать ссылку без потери объекта
56
arguments
• Как и this появляется при вызове • Это не Array
– нельзя forEach(), map(), filter() – можно for () {}
• Содержит список всех аргументов – arguments[0]… и .length
• Содержит ссылку на вызывающую функцию – arguments.caller – Deprecated!
• Содержит ссылку на текущую функцию – arguments.calle
http://es5.github.com/#x10.6
57
function myFunction(a) { console.log(arguments[0]); // 1 - ok a = 8; console.log(arguments[0]); // 8 - ??? } myFunction(1); function myFunctionStrict(a) { "use strict"; // <<< console.log(arguments[0]); // 1 - ok a = 8; console.log(arguments[0]); // 1 - ok } myFunctionStrict(1);
arguments и формальные параметры Без строгого режима arguments связан с формальными параметрами При добавлении "use strict" эта связь отменяется
58
JavaScript Циклы и Функции • for in
– Итерирует перечисляемые свойства (собственные и прототипа) – Используйте hasOwnProperty(name)
• Array.map().filter().reduce() • Function Expression • Function Declaration • Область видимости функции • Вызов функции и this
– this зависит от способа вызова функции
• Аргументы и arguments – arguments связан с формальными параметрами без StrictMode