Upgrade to Pro — share decks privately, control downloads, hide ads and more …

КРиПИ - JavaScript Циклы и Функции

КРиПИ - JavaScript Циклы и Функции

Mikhail Davydov

October 23, 2012
Tweet

More Decks by Mikhail Davydov

Other Decks in Education

Transcript

  1. View Slide

  2. Михаил Давыдов
    Разработчик JavaScript
    JavaScript
    Циклы и
    Функции

    View Slide

  3. Циклы – Statements
    for,
    while,
    do while,
    for in

    View Slide

  4. for, while, do while –
    работают так же как и во
    всех языках. Ура!

    View Slide

  5. for in
    •  Можно итерировать поля объекта
    •  Пробегает по перечисляемым свойствам
    –  По собственным свойствам
    –  И по свойствам прототипа
    •  Перечисляемость – скрытое свойство

    View Slide

  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: Пример

    View Slide

  7. 7
    hasOwnProperty и toString и
    др. – не перечисляемые
    свойства

    View Slide

  8. 8
    // А что если?
    Object.prototype.toString =
    function () {};

    View Slide

  9. 9
    Если toString и другие
    переписать, то они станут
    уже перечисляемыми

    View Slide

  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: Пример с загрязнением

    View Slide

  11. 11
    myValue – перечисляемое,
    но не собственное
    свойство

    View Slide

  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

    View Slide

  13. Циклы Expressions
    forEach
    map
    every, some
    filter
    reduce, reduceRight

    View Slide

  14. Как правило все циклы
    связаны с массивом

    View Slide

  15. Почему бы тогда не
    добавить итераторов к
    Array?!

    View Slide

  16. var persons = [{
    "name": "Ann",
    "age": 21
    }, {
    "name": "Helen",
    "age": 16
    }, {
    "name": "Peter",
    "age": 76
    }, {
    "name": "Jack",
    "age": 12
    }];
    Пример

    View Slide

  17. persons.forEach(): Undefined

    View Slide

  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 букву имени

    View Slide

  19. persons.map(): Array

    View Slide

  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(): получить только имена

    View Slide

  21. persons.some(): Boolean

    View Slide

  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(): есть ли пенсионеры?

    View Slide

  23. persons.every(): Boolean

    View Slide

  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(): все совершеннолетние?

    View Slide

  25. persons.filter(): Array

    View Slide

  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(): список несовершеннолетних

    View Slide

  27. persons.reduce(): *

    View Slide

  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(): средний возраст

    View Slide

  29. Цепочки вызовов
    persons.filter().map().join()

    View Slide

  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
    Получить имена совершеннолетних

    View Slide

  31. Внимание все они не
    поддерживаются старыми
    браузерами!
    5+ 3+ 10+ 3.2+ 9+

    View Slide

  32. Функции
    Function Declaration,
    Conditional Function Declaration,
    Function Expression,
    Named Function Expression,
    IEFE

    View Slide

  33. 33
    На самом деле Function в
    JavaScript – это Object со
    скрытым полем [[Call]]
    http://es5.github.com/#x13.2

    View Slide

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

    View Slide

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

    View Slide

  36. 36
    - При использовании строгого режима возникнет ошибка SyntaxError
    "use strict";
    if (true) {
    function a() {
    return 1;
    }
    } else {
    function a() {
    return 2;
    }
    }
    // SyntaxError
    // Function Expression!
    CFD+Strict Mode

    View Slide

  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

    View Slide

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

    View Slide

  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 – Замыкание, Модуль

    View Slide

  40. 40
    !function (){}(); // OK
    +function (){}(); // OK
    *function (){}(); // OK
    (function (){}()); // OK
    [function (){}()]; // OK
    var a = function (){}(); // Можно и так
    var a = (function (){}()); // Но лучше скобки оставлять
    IEFE

    View Slide

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

    View Slide

  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

    View Slide

  43. 43
    Цепочка областей видимости
    GLOBAL
    a 1
    foo func(on
    foo
    c 2
    bar func(on
    bar
    e argument

    View Slide

  44. 44
    Вся эта цепочка остается в
    памяти, пока жива функция
    bar()

    View Slide

  45. 45
    // Замыкание
    var getMySecret = (function () {
    // Это значение нельзя изменить
    var mySecret = Math.sin(Math.PI / 3);
    return function () {
    return mySecret;
    };
    }());
    // Можем только получать
    getMySecret(); // 0.8660254037844386
    typeof mySecret === "undefined";
    Пример области видимости

    View Slide

  46. Вызов функции и this
    this – основная грабля в JavaScript
    Прямой вызов
    Вызов через c оператором точка и []
    Вызов через new
    Вызов через call, apply, bind

    View Slide

  47. 47
    This в JavaScript
    определяется во время
    вызова функции!
    http://es5.github.com/#x11.2.3

    View Slide

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

    View Slide

  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

    View Slide

  50. 50
    Легко запомнить: что
    находится до "точки"
    является this

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  54. Вызов функции: arguments
    Передача значения
    arguments

    View Slide

  55. 55
    Передача значения в функцию
    •  Значения передаются по ссылке
    •  Можно менять «поля» переданного объекта
    •  Примитив менять нельзя
    •  Можно переписать ссылку без потери
    объекта

    View Slide

  56. 56
    arguments
    •  Как и this появляется при вызове
    •  Это не Array
    –  нельзя forEach(), map(), filter()
    –  можно for () {}
    •  Содержит список всех аргументов
    –  arguments[0]… и .length
    •  Содержит ссылку на вызывающую функцию
    –  arguments.caller
    –  Deprecated!
    •  Содержит ссылку на текущую функцию
    –  arguments.calle
    http://es5.github.com/#x10.6

    View Slide

  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" эта связь отменяется

    View Slide

  58. 58
    JavaScript Циклы и Функции
    •  for in
    –  Итерирует перечисляемые свойства (собственные и прототипа)
    –  Используйте hasOwnProperty(name)
    •  Array.map().filter().reduce()
    •  Function Expression
    •  Function Declaration
    •  Область видимости функции
    •  Вызов функции и this
    –  this зависит от способа вызова функции
    •  Аргументы и arguments
    –  arguments связан с формальными параметрами без StrictMode

    View Slide

  59. Михаил Давыдов
    Разработчик JavaScript
    [email protected]
    azproduction
    Спасибо

    View Slide