Михаил Давыдов
Разработчик 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
Михаил Давыдов
Разработчик JavaScript
azproduction@yandex-team.ru
azproduction
Спасибо

JavaScript. Loops and functions (in russian)

  • 2.
  • 3.
  • 4.
    for, while, dowhile – работают так же как и во всех языках. Ура!
  • 5.
    for in •  Можноитерировать поля объекта •  Пробегает по перечисляемым свойствам –  По собственным свойствам –  И по свойствам прототипа •  Перечисляемость – скрытое свойство
  • 6.
    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.
    7 hasOwnProperty и toStringи др. – не перечисляемые свойства
  • 8.
    8 // А чтоесли? Object.prototype.toString = function () {};
  • 9.
    9 Если toString идругие переписать, то они станут уже перечисляемыми
  • 10.
    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.
    11 myValue – перечисляемое, ноне собственное свойство
  • 12.
    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
  • 13.
  • 14.
    Как правило всециклы связаны с массивом
  • 15.
    Почему бы тогдане добавить итераторов к Array?!
  • 16.
    var persons =[{ "name": "Ann", "age": 21 }, { "name": "Helen", "age": 16 }, { "name": "Peter", "age": 76 }, { "name": "Jack", "age": 12 }]; Пример
  • 17.
  • 18.
    // Слишком многошума и лишних слов 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 букву имени
  • 19.
  • 20.
    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(): получить только имена
  • 21.
  • 22.
    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(): есть ли пенсионеры?
  • 23.
  • 24.
    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(): все совершеннолетние?
  • 25.
  • 26.
    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(): список несовершеннолетних
  • 27.
  • 28.
    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(): средний возраст
  • 29.
  • 30.
    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 Получить имена совершеннолетних
  • 31.
    Внимание все онине поддерживаются старыми браузерами! 5+ 3+ 10+ 3.2+ 9+
  • 32.
    Функции Function Declaration, Conditional FunctionDeclaration, Function Expression, Named Function Expression, IEFE
  • 33.
    33 На самом делеFunction в JavaScript – это Object со скрытым полем [[Call]] http://es5.github.com/#x13.2
  • 34.
    34 - Это Statement -Инициализируется во время входа в контекст - Объявляется в блоке функции или в глобальном блоке a(); // OK function a() { b(); // OK function b() { } } a(); Function Declaration/Definition http://es5.github.com/#x13
  • 35.
    35 - Это тожеStatement - Инициализируется во время входа в контекст или в рантайме - По стандарту такая запись недопустима if (true) { function a() { return 1; } } else { function a() { return 2; } } a(); // Firefox – 1, Others - 2 Conditional Function Declaration
  • 36.
    36 - При использованиистрогого режима возникнет ошибка SyntaxError "use strict"; if (true) { function a() { return 1; } } else { function a() { return 2; } } // SyntaxError // Function Expression! CFD+Strict Mode
  • 37.
    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.
    38 - Это тотже Function Expression - Можно обратиться к себе по своему имени - Имя доступно только в своем блоке (кроме старых IE) (function timer() { setTimeout(timer, 1000); console.log(+new Date); }()); typeof timer; // undefined, Old IE - function Named Function Expression
  • 39.
    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.
    40 !function (){}(); //OK +function (){}(); // OK *function (){}(); // OK (function (){}()); // OK [function (){}()]; // OK var a = function (){}(); // Можно и так var a = (function (){}()); // Но лучше скобки оставлять IEFE
  • 41.
    Область видимости Определяется вовремя создания функции Не меняется при передаче функции Образует цепочку областей видимости Лексическая Образует «замыкание»
  • 42.
    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.
    43 Цепочка областей видимости GLOBAL a1 foo func(on foo c 2 bar func(on bar e argument
  • 44.
    44 Вся эта цепочкаостается в памяти, пока жива функция bar()
  • 45.
    45 // Замыкание var getMySecret= (function () { // Это значение нельзя изменить var mySecret = Math.sin(Math.PI / 3); return function () { return mySecret; }; }()); // Можем только получать getMySecret(); // 0.8660254037844386 typeof mySecret === "undefined"; Пример области видимости
  • 46.
    Вызов функции иthis this – основная грабля в JavaScript Прямой вызов Вызов через c оператором точка и [] Вызов через new Вызов через call, apply, bind
  • 47.
    47 This в JavaScript определяетсяво время вызова функции! http://es5.github.com/#x11.2.3
  • 48.
    48 () – этооператор вызова функции this всегда undefined но он трансформируется в global В строгом режиме всегда undefined (трансформации нет) function a() { console.log(this); } a(); // window (undefined -> window) function b() { "use strict"; console.log(this); } b(); // undefined Прямой вызов – через оператор ()
  • 49.
    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.
    50 Легко запомнить: что находитсядо "точки" является this
  • 51.
    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.
    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.
    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
  • 54.
  • 55.
    55 Передача значения вфункцию •  Значения передаются по ссылке •  Можно менять «поля» переданного объекта •  Примитив менять нельзя •  Можно переписать ссылку без потери объекта
  • 56.
    56 arguments •  Как иthis появляется при вызове •  Это не Array –  нельзя forEach(), map(), filter() –  можно for () {} •  Содержит список всех аргументов –  arguments[0]… и .length •  Содержит ссылку на вызывающую функцию –  arguments.caller –  Deprecated! •  Содержит ссылку на текущую функцию –  arguments.calle http://es5.github.com/#x10.6
  • 57.
    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.
    58 JavaScript Циклы иФункции •  for in –  Итерирует перечисляемые свойства (собственные и прототипа) –  Используйте hasOwnProperty(name) •  Array.map().filter().reduce() •  Function Expression •  Function Declaration •  Область видимости функции •  Вызов функции и this –  this зависит от способа вызова функции •  Аргументы и arguments –  arguments связан с формальными параметрами без StrictMode
  • 59.