SlideShare uma empresa Scribd logo
1 de 31
Baixar para ler offline
Как программировать на
JavaScript и не выстрелить
       себе в ногу




                   Андрей Геоня
                    29.12.2011
С чем имеем дело?

● ОО подход основан на прототипах;
● Отсутствие пространств имен;
● Отсутствие ограничения области видимости;
● Отсутствие строгой типизации;
● Отсутствие проверки статических элементов.
Прототипное программирование
function Human() {
   console.log('Human constructor called');
}
Human.prototype = {
   sayHuman: function() { alert('I am a Human!'); },
   sayHello: function() { alert('Hello world!'); }
}
// human.__proto__ = instance of Object
var human = new Human();

function Man() {
  console.log('Man constructor called');
}
Man.prototype = new Human();
Man.prototype.sayMan = function() {
  alert('I am a Man!');
}

function Woman() {
  console.log('Woman constructor called');
}
Woman.prototype = new Human();
Woman.prototype.sayWoman = function() {
  alert('I am a Woman!');
}

var peter = new Man(); // peter.__proto__ = instance of Human
var olga = new Woman(); // olga.__proto__ = instance of Human
Интерфейсы. Классика


interface MyInterface1 {
   public function add($param1);
   public function remove($param1);
}
interface MyInterface2 {
   public function display($param1, $param2);
}

class MyClass implements MyInterface1, MyInterface2 {
   public function add($param1) { ... }
   public function remove(param1) { ... }
   public function display($param1, $param2) { ... }
}
Эмуляция интерфейсов в JS с помощью комментариев


/*
interface MyInterface1 {
   function add(param1);
   function remove(param1);
}
interface MyInterface2 {
   function display(param1, param2);
}
*/

var MyClass = function() { // implements MyInterface1, MyInterface2
   ...
};
MyClass.prototype.add = function(param1) { ... };
MyClass.prototype.remove = function(param1) { ... };
MyClass.prototype.display = function(param1, param2) { ... };
Эмуляция интерфейсов в JS с помощью простой проверки
/*
interface MyInterface1 {
   function add(param1);
   function remove(param1);
}
interface MyInterface2 {
   function display(param1, param2);
}
*/

var MyClass = function() {
   this.implementsInterfaces = ['MyInterface1', 'MyInterface2'];
   ...
};

function someClient(someInstance) {
  if(!implements(someInstance, 'MyInterface1', 'MyInterface2')) {
      throw new Error("Object does not implement a required interface.");
  }
  ...
}

// Проверяет, есть ли в массиве object.implementsInterfaces нужные названия интерфейсов
function implements(object) {
   ...
}
Эмуляция интерфейсов в JS. Объекты + проверка методов
var MyInterface1 = new Interface('MyInterface1', ['add', 'remove']);
var MyInterface2 = new Interface('MyInterface2', ['display']);

var MyClass = function() { // implements MyInterface1, MyInterface2
   ...
};

function someClient(someInstance) {
  // выбросит Exception, если в object отсутствуют нужные методы
  Interface.ensureImplements(someInstance, MyInterface1, MyInterface2));
  ...
}
Конструктор Interface

var Interface = function(name, methods) {
    if(arguments.length != 2) {
       throw new Error("Interface constructor called with " + arguments.length +
          "arguments, but expected exactly 2.");
    }
    this.name = name;
    this.methods = [];
    for(var i = 0, len = methods.length; i < len; i++) {
  if(typeof methods[i] !== 'string') {
          throw new Error("Interface constructor expects method names to be passed in as a string.");
       }
       this.methods.push(methods[i]);
    }
};
Статический метод Interface.ensureImplements
Interface.ensureImplements = function(object) {
   if(arguments.length < 2) {
      throw new Error("Function Interface.ensureImplements called with " +
          arguments.length + "arguments, but expected at least 2.");
   }
   for(var i = 1, len = arguments.length; i < len; i++) {
      var interface = arguments[i];
      if(interface.constructor !== Interface) {
          throw new Error("Function Interface.ensureImplements expects arguments"
              + "two and above to be instances of Interface.");
      }
      for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
          var method = interface.methods[j];
          if(!object[method] || typeof object[method] !== 'function') {
              throw new Error("Function Interface.ensureImplements: object "
                 + "does not implement the " + interface.name
                 + " interface. Method " + method + " was not found.");
          }
      }
   }
};
Инкапсуляция на соглашениях
var IHuman = new Interface('Human', ['getSurname', 'setSurname', 'getName', 'setName']);

var Human = function (surname, name) {
  this.setSurname(surname);
  this.setName(name);
}
Human.prototype = {
  getSurname: function() {
     return this._surname;
  },
  setSurname: function(surname) {
     if (!this._isset(surname)) {
         throw new Error('Surname is required')
     };
     this._surname = surname;
  },
  getName: function() {
     return this._name;
  },
  setName: function(name) {
     this._name = name || null;
  },
  _isset: function(s) {
     if (s == undefined || typeof s != 'string') { return false; }
     else { return true; }
  }
}
Замыкания
Замыкание — это особый вид функции. Она определена в теле другой функции и создаётся
каждый раз во время её выполнения. При этом вложенная внутренняя функция содержит ссылки
на локальные переменные внешней функции. Каждый раз при выполнении внешней функции
происходит создание нового экземпляра внутренней функции, с новыми ссылками на переменные
внешней функции.

function foo() {
  var a = 10;
  function bar() {
     a *= 2;
     return a;
  }
  return bar;
}

var baz = foo(); // baz is now a reference to function bar
baz(); // returns 20
baz(); // returns 40
baz(); // returns 80

var blat = foo(); // blat is another reference to bar
blat(); // returns 20
Инкапсуляция на замыканиях
var Human = function (newSurname, newName) {
  var name, surname;
  function isset(s) {
     if (s == undefined || typeof s != 'string') { return false; } else { return true; }
  };
  // Privileged methods
  this.getSurname = function() {
     return surname;
  };
  this.setSurname = function(newSurname) {
     if (!isset(newSurname)) { throw new Error('Surname is required') };
     surname = newSurname;
  };
  this.getName = function() {
     return name;
  };
  this.setName = function(newName) {
     name = newName || null;
  };
  // Constructor code
  this.setSurname(newSurname);
  this.setName(newName);
}

Human.prototype = { // Public, non-privileged methods
   talk: function() {
      alert(this.getName() + this.getSurname());
   }
};
Статические атрибуты и методы
var Human = (function () {
  // Private static attribute and method
  var count = 0;
  function isset(s) { ... };

   // Return the constructor
   return function (newSurname, newName) {
      // Private attributes
      var name, surname;

        // Privileged methods
        this.getSurname = function() { ... };
        this.setSurname = function(newSurname) { ... };
        this.getName = function() { ... };
        this.setName = function(newName) { ... };

        // Constructor code
        count++;
        this.setSurname(newSurname);
        this.setName(newName);
   }
})();

// Public static method
Human.toUpperCase = function(s){ ... }

Human.prototype = { // Public, non-privileged methods
   talk: function() { ... }
};
Константы - приватные статические атрибуты с getter-ом


var Human = (function () {
  // Constant (created as private static attribute)
  var CLASS_NAME = 'Human';

  // Privileged static method
  this.getCLASS_NAME() {
     return CLASS_NAME;
  }

   // Return the constructor
   return function (newSurname, newName) {
      ...
   }
})();
Приватный объект с константами и getter-ом

var Human = (function () {
  // Private static attributes.
  var constants = {
     CLASS_NAME: 'Human',
     SOME_CONSTANT_1: 'Some value 1',
     SOME_CONSTANT_2: 'Some value 2'
  }

  // Privileged static method.
  this.getConstant(name) {
     return constants[name];
  }

   // Return the constructor
   return function (newSurname, newName) {
      ...
   }
})();
Эмуляция классического наследования
/* Class Person */
function Person(name) {
   this.name = name;
}
Person.prototype.getName = function() {
   return this.name;
}

/* Class Author */
function Author(name, books) {
   Person.call(this, name); // Call the superclass's constructor in the scope of this
   this.books = books; // Add an attribute to Author
}
Author.prototype = new Person(); // Set up the prototype chain
Author.prototype.constructor = Author; // Set the constructor attribute to Author
Author.prototype.getBooks = function() { // Add a method to Author
   return this.books;
}

var author1 = new Author('Jeff Six', ['Application Security for the Android Platform']);
var author2 = new Author('Vandad Nahavandipoor', ['iOS 5 Programming Cookbook']);
Эмуляция классического наследования. Функция extend
function extend(subClass, superClass) {
   var F = function() {};
   F.prototype = superClass.prototype;
   subClass.prototype = new F();
   subClass.prototype.constructor = subClass;
   subClass.superclass = superClass.prototype;
   if(superClass.prototype.constructor == Object.prototype.constructor) {
       superClass.prototype.constructor = superClass;
   }
}
/* Class Person */
function Person(name) {
   this.name = name;
}
Person.prototype.getName = function() {
   return this.name;
}
/* Class Author. */
function Author(name, books) {
   Author.superclass.constructor.call(this, name);
   this.books = books;
}
extend(Author, Person);
Author.prototype.getBooks = function() {
   return this.books;
};
var author1 = new Author('Jeff Six', ['Application Security for the Android Platform']);
var author2 = new Author('Vandad Nahavandipoor', ['iOS 5 Programming Cookbook']);
Инкапсуляция при эмуляции классического наследования


● В подклассе имеется доступ только к публичным и привилегированным членам
  родительского класса;

● Приватные члены родительского класса доступны в подклассах, а также извне
  только через привилегированные методы самого родительского класса;

● Если есть необходимость в protected членах, принято соглашение использовать
  подчеркивание, например var _myProtectedVar = null;
Прототипное наследование
/* Clone function */
function clone(object) {
   function F() {}
   F.prototype = object;
   return new F;
}

/* Person Prototype Object */
var Person = {
   name: 'default name',
   getName: function() {
     return this.name;
   }
}

/* Author Prototype Object */
var Author = clone(Person);
Author.books = []; // Default value
Author.getBooks = function() {
   return this.books;
}

var author1 = clone(Author); // Author-like object
author1.name = 'Jeff Six';
author1.books = ['Application Security for the Android Platform'];
var author2 = clone(Author); // Author-like object
author2.name = 'Vandad Nahavandipoor';
author2.books = ['iOS 5 Programming Cookbook'];
Mixin
/* Augment function. */
function augment(receivingClass, givingClass) {
   for(var methodName in givingClass.prototype) {
      if(!receivingClass.prototype[methodName]) {
          receivingClass.prototype[methodName] = givingClass.prototype[methodName];
      }
   }
}

/* Regular class */
var Class1 = function() {};
Class1.prototype = {
   method1: function() {},
   method2: function() {}
}

/* Mixin class */
var Class2 = function() {};
Class2.prototype = {
   mixinMethod1: function() { alert('mixinMethod1 called'); },
   mixinMethod2: function() { alert('mixinMethod2 called'); }
};

augment(Class1, Class2);
var myObj = new Class1();
myObj.mixinMethod1();
Singleton
/* Basic Singleton. */             /* Singleton with Private Members */
var Singleton = {                  MyNamespace.Singleton = (function() {
   attribute1: true,
   attribute2: 10,                    // Private members
   method1: function() {              var privateAttribute1 = false;
      ...                             var privateAttribute2 = [1, 2, 3];
   },                                 function privateMethod1() {
   method2: function(arg) {              ...
      ...                             }
   }                                  function privateMethod2(args) {
};                                       ...
                                      }

                                      return {
                                         // Public members
                                         publicAttribute1: true,
                                         publicAttribute2: 10,
                                         publicMethod1: function() {
                                            ...
                                         },
                                         publicMethod2: function(args) {
                                            ...
                                         }
                                      };

                                   })();
"Ленивое" инстанцирование
MyNamespace.Singleton = (function() {
   var instance;
   // All of the singleton code here
   function constructor() {
      var privateAttribute1 = false;
      function privateMethod1() {
          ...
      }
      return {
          publicAttribute1: true,
          publicMethod1: function() {
              ...
          }
      }
   }
   return {
      // Public members
      getInstance: function() {
          if(!instance) {
              instance = constructor();
          }
          return instance;
      }
   }
})();
MyNamespace.Singleton.getInstance().publicMethod1(); // Call singleton method
Простая Фабрика
var CarFactory = {
   createCar: function(model) {
     var car;
     switch(model) {
        case 'bmw':
           car = new BMW();
           break;
        case 'ford':
           car = new Ford();
           break;
        case 'ferrari':
        default:
           car = new Ferrari();
     }
     Interface.ensureImplements(car, Car);
     return car;
   }
};
Фабричный метод - паттерн, порождающий классы

/* CarShop class (abstract). */
var CarShop = function() {};
CarShop.prototype = {
   sellCar: function(model) {
     var car = this.createCar(model);

       car.prepare();
       car.wash();

       return car;
     },
     createCar: function(model) {
        throw new Error('Unsupported operation on an abstract class');
     }
};


     ● Используем абстрактный класс;
     ● Используем метод extend: extend(FordCarShop, CarShop);
     ● Используем при необходимости метод ensureImplements: Interface.ensureImplements
       (car, Car).
Компоновщик. Пример использования - запоминание форм
var contactForm = new CompositeForm('contact-form', 'POST', 'contact.php');

var nameFieldset = new CompositeFieldset('name-fieldset');
nameFieldset.add(new InputField('first-name', 'First Name'));
nameFieldset.add(new InputField('last-name', 'Last Name'));
contactForm.add(nameFieldset);

var addressFieldset = new CompositeFieldset('address-fieldset');
addressFieldset.add(new InputField('address', 'Address'));
addressFieldset.add(new InputField('city', 'City'));
addressFieldset.add(new SelectField('state', 'State', stateArray));
contactForm.add(addressFieldset);

contactForm.add(new TextareaField('comments', 'Comments'));

body.appendChild(contactForm.getElement());

addEvent(window, 'unload', contactForm.save);
addEvent(window, 'load', contactForm.restore);
addEvent('save-button', 'click', nameFieldset.save);
addEvent('restore-button', 'click', nameFieldset.restore);
Декораторы функций
Выглядит это так:

function upperCaseDecorator(func) {
  return function() {
     return func.apply(this, arguments).toUpperCase();
  }
}



Можно применять с пользой:

var gCollection = new YMaps.GeoObjectCollection();
gCollection = new TimeProfiler(gCollection); // Декорируем все методы профайлером

gCollection.add([
    new YMaps.Placemark(new YMaps.GeoPoint(37.518234, 55.708937)),
    new YMaps.Placemark(new YMaps.GeoPoint(37.514146, 55.722294)),
    new YMaps.Placemark(new YMaps.GeoPoint(37.514146, 55.722225)),
    new YMaps.Placemark(new YMaps.GeoPoint(37.514146, 55.722236))
]);
gCollection.removeAll();

С помощью декоратора TimeProfiler, в консоли будет напечатано время выполнения
методов add и removeAll.
Тренируем внимание
  ● Расширение встроенных прототипов языка - зло;
  ● Не забываем писать var;
  ● Учитываем зависимость производительности от длины цепочек прототипов;
  ● Цикл for in проходит по всей цепочке прототипов. Решение - hasOwnProperty;
  ● JavaScript не резервирует свойство с именем hasOwnProperty, но можно делать
     так: ({}).hasOwnProperty.call(obj, 'propertyName');
  ● Обходить обычный массив с помощью for in - зло;
  ● Ключевое слово this ссылается на контекст вызова, но его можно явно задать при
     call и apply;
  ● arguments не является наследником Array, у него нет push, pop, slice и т.д.;
  ● Помним про высасывание определений вверх ближайшей области видимости;
  ● Используем instanceof только собственных типов. Для стандартных типов - зло;
  ● eval - зло: а) безопасность; б) косвенный вызов и выход из локального scope;
  ● for(var i = 0; i < 10; i++) {
      setTimeout(function() { console.log(i); }, 1000);
   }
Числа 0-9 не будут напечатаны, так как анонимная функция сохраняет ссылку на
переменную i, которая в момент вызова будет равна 10. Решение:
   for(var i = 0; i < 10; i++) {
      (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i);
   }
Сравниваем осторожно

Оператор нестрогого равенства:        Оператор строгого равенства:


""          ==   "0"       false        ""          === "0"       false
0           ==   ""        true         0           === ""        false
0           ==   "0"       true         0           === "0"       false
false       ==   "false"   false        false       === "false"   false
false       ==   "0"       true         false       === "0"       false
false       ==   undefined false        false       === undefined false

false       ==   null      false        false       === null      false
null        ==   undefined true         null        === undefined false
" trn"   ==   0         true         " trn"   === 0         false
Внимание, оператор typeof

Результат работы typeof (простите, но так исторически сложилось...):

Значение               [[Class]] = Object.prototype.toString. Тип
                       call(myObj)
"foo"                  String                                 string
new String("foo")      String                                 object
1.2                    Number                                 number
new Number(1.2)        Number                                 object
true                   Boolean                                boolean
new Boolean(true)      Boolean                                object
new Date()             Date                                   object
new Error()            Error                                  object
[1,2,3]                Array                                  object
new Array(1, 2, 3)     Array                                  object
new Function("")       Function                               function
/abc/g                 RegExp                                 object (function в Nitro/V8)
new RegExp("meow")     RegExp                                 object (function в Nitro/V8)
{}                     Object                                 object
new Object()           Object                                 object
Почитать

● Pro JavaScript design patterns (Ross Harmes, Dustin Diaz);
● JavaScript Garden: http://shamansir.github.com/JavaScript-Garden/;
● MDN: https://developer.mozilla.org/en/JavaScript;
● http://javascript.ru/.
Как программировать на JavaScript и не выстрелить себе в ногу

Mais conteúdo relacionado

Mais procurados

Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Яковенко Кирилл
 
Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Sergey Schetinin
 
JavaScript. Loops and functions (in russian)
JavaScript. Loops and functions (in russian)JavaScript. Loops and functions (in russian)
JavaScript. Loops and functions (in russian)Mikhail Davydov
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в DjangoMoscowDjango
 
Артем Яворский "@babel/core": "7.x"
Артем Яворский "@babel/core": "7.x"Артем Яворский "@babel/core": "7.x"
Артем Яворский "@babel/core": "7.x"Fwdays
 
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev FedorProgramming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev FedorFedor Lavrentyev
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPython Meetup
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Vasya Petrov
 
JPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаJPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаAnton Arhipov
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Alexander Granin
 
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.Roman Brovko
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормозаAlexander Shigin
 
Лекция 10. Классы 2.
Лекция 10. Классы 2.Лекция 10. Классы 2.
Лекция 10. Классы 2.Roman Brovko
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in actionYuri Trukhin
 
Влад Ковташ — Yap Database
Влад Ковташ — Yap DatabaseВлад Ковташ — Yap Database
Влад Ковташ — Yap DatabaseCocoaHeads
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Roman Brovko
 
Курсы по мобильной разработке. 1 лекция. Знакомство с iOS
Курсы по мобильной разработке. 1 лекция. Знакомство с iOSКурсы по мобильной разработке. 1 лекция. Знакомство с iOS
Курсы по мобильной разработке. 1 лекция. Знакомство с iOSГлеб Тарасов
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.Roman Brovko
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Roman Brovko
 

Mais procurados (20)

Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
 
Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование
 
JavaScript. Loops and functions (in russian)
JavaScript. Loops and functions (in russian)JavaScript. Loops and functions (in russian)
JavaScript. Loops and functions (in russian)
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в Django
 
Артем Яворский "@babel/core": "7.x"
Артем Яворский "@babel/core": "7.x"Артем Яворский "@babel/core": "7.x"
Артем Яворский "@babel/core": "7.x"
 
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev FedorProgramming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
 
Pyton – пробуем функциональный стиль
Pyton – пробуем функциональный стильPyton – пробуем функциональный стиль
Pyton – пробуем функциональный стиль
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
JPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаJPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчика
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
 
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.
 
Python и его тормоза
Python и его тормозаPython и его тормоза
Python и его тормоза
 
Лекция 10. Классы 2.
Лекция 10. Классы 2.Лекция 10. Классы 2.
Лекция 10. Классы 2.
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in action
 
Влад Ковташ — Yap Database
Влад Ковташ — Yap DatabaseВлад Ковташ — Yap Database
Влад Ковташ — Yap Database
 
msumobi2. Лекция 2
msumobi2. Лекция 2msumobi2. Лекция 2
msumobi2. Лекция 2
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.
 
Курсы по мобильной разработке. 1 лекция. Знакомство с iOS
Курсы по мобильной разработке. 1 лекция. Знакомство с iOSКурсы по мобильной разработке. 1 лекция. Знакомство с iOS
Курсы по мобильной разработке. 1 лекция. Знакомство с iOS
 
Лекция 4. Строки, байты, файлы и ввод/вывод.
 Лекция 4. Строки, байты, файлы и ввод/вывод. Лекция 4. Строки, байты, файлы и ввод/вывод.
Лекция 4. Строки, байты, файлы и ввод/вывод.
 
Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.Лекция 9. Модули, пакеты и система импорта.
Лекция 9. Модули, пакеты и система импорта.
 

Destaque

טוני פיין פוטוני בפרחים יפים בישראל
טוני פיין   פוטוני בפרחים יפים בישראלטוני פיין   פוטוני בפרחים יפים בישראל
טוני פיין פוטוני בפרחים יפים בישראלרם מנשה
 
ממצגת ללא כותרת
ממצגת ללא כותרתממצגת ללא כותרת
ממצגת ללא כותרתרם מנשה
 
Montalti - "Context aware applications" (2011, master thesys ITA)
Montalti - "Context aware applications" (2011, master thesys ITA)Montalti - "Context aware applications" (2011, master thesys ITA)
Montalti - "Context aware applications" (2011, master thesys ITA)Alessandro Montalti
 
What to know when working with children in your research, university of guelph
What to know when working with children in your research, university of guelphWhat to know when working with children in your research, university of guelph
What to know when working with children in your research, university of guelphManuel García
 
AIESEC BANGALORE :Gapbridge software Pvt Ltd
AIESEC BANGALORE :Gapbridge software Pvt LtdAIESEC BANGALORE :Gapbridge software Pvt Ltd
AIESEC BANGALORE :Gapbridge software Pvt LtdGurupreet Kaushik
 
Ten Commandments for Teammates
Ten Commandments for TeammatesTen Commandments for Teammates
Ten Commandments for TeammatesMichael Maisel
 
Edu 513 Nonlinguistic Representations
Edu 513 Nonlinguistic RepresentationsEdu 513 Nonlinguistic Representations
Edu 513 Nonlinguistic Representationsjenniferbehr
 
Cumbria Cruises - Aurora
Cumbria Cruises - AuroraCumbria Cruises - Aurora
Cumbria Cruises - AuroraCumbria Cruises
 
Cumbria cruises - Oceana
Cumbria cruises - OceanaCumbria cruises - Oceana
Cumbria cruises - OceanaCumbria Cruises
 
Cumbria cruises - Arcadia
Cumbria cruises - ArcadiaCumbria cruises - Arcadia
Cumbria cruises - ArcadiaCumbria Cruises
 
Connect building success v2
Connect   building success v2Connect   building success v2
Connect building success v2Wendy Bruun
 
Ten Commandments for Teammates
Ten Commandments for TeammatesTen Commandments for Teammates
Ten Commandments for TeammatesMichael Maisel
 
Ten Commandments for Teammates
Ten Commandments for TeammatesTen Commandments for Teammates
Ten Commandments for TeammatesMichael Maisel
 
PROTA IPA KLS VI
PROTA IPA KLS VIPROTA IPA KLS VI
PROTA IPA KLS VIsutarso
 

Destaque (20)

טוני פיין פוטוני בפרחים יפים בישראל
טוני פיין   פוטוני בפרחים יפים בישראלטוני פיין   פוטוני בפרחים יפים בישראל
טוני פיין פוטוני בפרחים יפים בישראל
 
ממצגת ללא כותרת
ממצגת ללא כותרתממצגת ללא כותרת
ממצגת ללא כותרת
 
Montalti - "Context aware applications" (2011, master thesys ITA)
Montalti - "Context aware applications" (2011, master thesys ITA)Montalti - "Context aware applications" (2011, master thesys ITA)
Montalti - "Context aware applications" (2011, master thesys ITA)
 
What to know when working with children in your research, university of guelph
What to know when working with children in your research, university of guelphWhat to know when working with children in your research, university of guelph
What to know when working with children in your research, university of guelph
 
AIESEC BANGALORE :Gapbridge software Pvt Ltd
AIESEC BANGALORE :Gapbridge software Pvt LtdAIESEC BANGALORE :Gapbridge software Pvt Ltd
AIESEC BANGALORE :Gapbridge software Pvt Ltd
 
Presentation jadi
Presentation jadiPresentation jadi
Presentation jadi
 
Ten Commandments for Teammates
Ten Commandments for TeammatesTen Commandments for Teammates
Ten Commandments for Teammates
 
Edu 513 Nonlinguistic Representations
Edu 513 Nonlinguistic RepresentationsEdu 513 Nonlinguistic Representations
Edu 513 Nonlinguistic Representations
 
Cumbria Cruises - Aurora
Cumbria Cruises - AuroraCumbria Cruises - Aurora
Cumbria Cruises - Aurora
 
Fitness
FitnessFitness
Fitness
 
Cumbria cruises - Oceana
Cumbria cruises - OceanaCumbria cruises - Oceana
Cumbria cruises - Oceana
 
Cumbria cruises - Arcadia
Cumbria cruises - ArcadiaCumbria cruises - Arcadia
Cumbria cruises - Arcadia
 
Good to Great Boss
Good to Great BossGood to Great Boss
Good to Great Boss
 
Connect building success v2
Connect   building success v2Connect   building success v2
Connect building success v2
 
Ten Commandments for Teammates
Ten Commandments for TeammatesTen Commandments for Teammates
Ten Commandments for Teammates
 
Ten Commandments for Teammates
Ten Commandments for TeammatesTen Commandments for Teammates
Ten Commandments for Teammates
 
Dslr
DslrDslr
Dslr
 
Review ppt
Review pptReview ppt
Review ppt
 
PROTA IPA KLS VI
PROTA IPA KLS VIPROTA IPA KLS VI
PROTA IPA KLS VI
 
Horse genetics
Horse geneticsHorse genetics
Horse genetics
 

Semelhante a Как программировать на JavaScript и не выстрелить себе в ногу

I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jqueryITmozg
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?Vasil Remeniuk
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий solit
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияYandex
 
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScriptСтажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScriptSmartTools
 
функции в Java script
функции в Java scriptфункции в Java script
функции в Java scriptViktor Andreev
 
Михаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияМихаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияYandex
 
Михаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxМихаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxYandex
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)Ontico
 
Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Stfalcon Meetups
 
Groovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всёмGroovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всёмRuslan Balkin
 
Functional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalFunctional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalAndrei Solntsev
 
C# Desktop. Занятие 03.
C# Desktop. Занятие 03.C# Desktop. Занятие 03.
C# Desktop. Занятие 03.Igor Shkulipa
 
Statis code analysis
Statis code analysisStatis code analysis
Statis code analysischashnikov
 
JavaScript. Async (in Russian)
JavaScript. Async (in Russian)JavaScript. Async (in Russian)
JavaScript. Async (in Russian)Mikhail Davydov
 

Semelhante a Как программировать на JavaScript и не выстрелить себе в ногу (20)

I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jquery
 
Асинхронный JavaScript
Асинхронный JavaScriptАсинхронный JavaScript
Асинхронный JavaScript
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
 
course js day 2
course js day 2course js day 2
course js day 2
 
Михаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знанияМихаил Давыдов — JavaScript: Базовые знания
Михаил Давыдов — JavaScript: Базовые знания
 
Lecture 8
Lecture 8Lecture 8
Lecture 8
 
Lecture 5
Lecture 5Lecture 5
Lecture 5
 
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScriptСтажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
 
функции в Java script
функции в Java scriptфункции в Java script
функции в Java script
 
Михаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знанияМихаил Давыдов - JavaScript. Базовые знания
Михаил Давыдов - JavaScript. Базовые знания
 
Михаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajaxМихаил Давыдов - Транспорт, ajax
Михаил Давыдов - Транспорт, ajax
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
 
Discovering Lambdas in Java 8
Discovering Lambdas in Java 8Discovering Lambdas in Java 8
Discovering Lambdas in Java 8
 
Groovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всёмGroovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всём
 
Functional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - finalFunctional Programming Dev Club 2009 - final
Functional Programming Dev Club 2009 - final
 
C# Desktop. Занятие 03.
C# Desktop. Занятие 03.C# Desktop. Занятие 03.
C# Desktop. Занятие 03.
 
Statis code analysis
Statis code analysisStatis code analysis
Statis code analysis
 
JavaScript. Async (in Russian)
JavaScript. Async (in Russian)JavaScript. Async (in Russian)
JavaScript. Async (in Russian)
 
C sharp deep dive
C sharp deep diveC sharp deep dive
C sharp deep dive
 

Как программировать на JavaScript и не выстрелить себе в ногу

  • 1. Как программировать на JavaScript и не выстрелить себе в ногу Андрей Геоня 29.12.2011
  • 2. С чем имеем дело? ● ОО подход основан на прототипах; ● Отсутствие пространств имен; ● Отсутствие ограничения области видимости; ● Отсутствие строгой типизации; ● Отсутствие проверки статических элементов.
  • 3. Прототипное программирование function Human() { console.log('Human constructor called'); } Human.prototype = { sayHuman: function() { alert('I am a Human!'); }, sayHello: function() { alert('Hello world!'); } } // human.__proto__ = instance of Object var human = new Human(); function Man() { console.log('Man constructor called'); } Man.prototype = new Human(); Man.prototype.sayMan = function() { alert('I am a Man!'); } function Woman() { console.log('Woman constructor called'); } Woman.prototype = new Human(); Woman.prototype.sayWoman = function() { alert('I am a Woman!'); } var peter = new Man(); // peter.__proto__ = instance of Human var olga = new Woman(); // olga.__proto__ = instance of Human
  • 4. Интерфейсы. Классика interface MyInterface1 { public function add($param1); public function remove($param1); } interface MyInterface2 { public function display($param1, $param2); } class MyClass implements MyInterface1, MyInterface2 { public function add($param1) { ... } public function remove(param1) { ... } public function display($param1, $param2) { ... } }
  • 5. Эмуляция интерфейсов в JS с помощью комментариев /* interface MyInterface1 { function add(param1); function remove(param1); } interface MyInterface2 { function display(param1, param2); } */ var MyClass = function() { // implements MyInterface1, MyInterface2 ... }; MyClass.prototype.add = function(param1) { ... }; MyClass.prototype.remove = function(param1) { ... }; MyClass.prototype.display = function(param1, param2) { ... };
  • 6. Эмуляция интерфейсов в JS с помощью простой проверки /* interface MyInterface1 { function add(param1); function remove(param1); } interface MyInterface2 { function display(param1, param2); } */ var MyClass = function() { this.implementsInterfaces = ['MyInterface1', 'MyInterface2']; ... }; function someClient(someInstance) { if(!implements(someInstance, 'MyInterface1', 'MyInterface2')) { throw new Error("Object does not implement a required interface."); } ... } // Проверяет, есть ли в массиве object.implementsInterfaces нужные названия интерфейсов function implements(object) { ... }
  • 7. Эмуляция интерфейсов в JS. Объекты + проверка методов var MyInterface1 = new Interface('MyInterface1', ['add', 'remove']); var MyInterface2 = new Interface('MyInterface2', ['display']); var MyClass = function() { // implements MyInterface1, MyInterface2 ... }; function someClient(someInstance) { // выбросит Exception, если в object отсутствуют нужные методы Interface.ensureImplements(someInstance, MyInterface1, MyInterface2)); ... }
  • 8. Конструктор Interface var Interface = function(name, methods) { if(arguments.length != 2) { throw new Error("Interface constructor called with " + arguments.length + "arguments, but expected exactly 2."); } this.name = name; this.methods = []; for(var i = 0, len = methods.length; i < len; i++) { if(typeof methods[i] !== 'string') { throw new Error("Interface constructor expects method names to be passed in as a string."); } this.methods.push(methods[i]); } };
  • 9. Статический метод Interface.ensureImplements Interface.ensureImplements = function(object) { if(arguments.length < 2) { throw new Error("Function Interface.ensureImplements called with " + arguments.length + "arguments, but expected at least 2."); } for(var i = 1, len = arguments.length; i < len; i++) { var interface = arguments[i]; if(interface.constructor !== Interface) { throw new Error("Function Interface.ensureImplements expects arguments" + "two and above to be instances of Interface."); } for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) { var method = interface.methods[j]; if(!object[method] || typeof object[method] !== 'function') { throw new Error("Function Interface.ensureImplements: object " + "does not implement the " + interface.name + " interface. Method " + method + " was not found."); } } } };
  • 10. Инкапсуляция на соглашениях var IHuman = new Interface('Human', ['getSurname', 'setSurname', 'getName', 'setName']); var Human = function (surname, name) { this.setSurname(surname); this.setName(name); } Human.prototype = { getSurname: function() { return this._surname; }, setSurname: function(surname) { if (!this._isset(surname)) { throw new Error('Surname is required') }; this._surname = surname; }, getName: function() { return this._name; }, setName: function(name) { this._name = name || null; }, _isset: function(s) { if (s == undefined || typeof s != 'string') { return false; } else { return true; } } }
  • 11. Замыкания Замыкание — это особый вид функции. Она определена в теле другой функции и создаётся каждый раз во время её выполнения. При этом вложенная внутренняя функция содержит ссылки на локальные переменные внешней функции. Каждый раз при выполнении внешней функции происходит создание нового экземпляра внутренней функции, с новыми ссылками на переменные внешней функции. function foo() { var a = 10; function bar() { a *= 2; return a; } return bar; } var baz = foo(); // baz is now a reference to function bar baz(); // returns 20 baz(); // returns 40 baz(); // returns 80 var blat = foo(); // blat is another reference to bar blat(); // returns 20
  • 12. Инкапсуляция на замыканиях var Human = function (newSurname, newName) { var name, surname; function isset(s) { if (s == undefined || typeof s != 'string') { return false; } else { return true; } }; // Privileged methods this.getSurname = function() { return surname; }; this.setSurname = function(newSurname) { if (!isset(newSurname)) { throw new Error('Surname is required') }; surname = newSurname; }; this.getName = function() { return name; }; this.setName = function(newName) { name = newName || null; }; // Constructor code this.setSurname(newSurname); this.setName(newName); } Human.prototype = { // Public, non-privileged methods talk: function() { alert(this.getName() + this.getSurname()); } };
  • 13. Статические атрибуты и методы var Human = (function () { // Private static attribute and method var count = 0; function isset(s) { ... }; // Return the constructor return function (newSurname, newName) { // Private attributes var name, surname; // Privileged methods this.getSurname = function() { ... }; this.setSurname = function(newSurname) { ... }; this.getName = function() { ... }; this.setName = function(newName) { ... }; // Constructor code count++; this.setSurname(newSurname); this.setName(newName); } })(); // Public static method Human.toUpperCase = function(s){ ... } Human.prototype = { // Public, non-privileged methods talk: function() { ... } };
  • 14. Константы - приватные статические атрибуты с getter-ом var Human = (function () { // Constant (created as private static attribute) var CLASS_NAME = 'Human'; // Privileged static method this.getCLASS_NAME() { return CLASS_NAME; } // Return the constructor return function (newSurname, newName) { ... } })();
  • 15. Приватный объект с константами и getter-ом var Human = (function () { // Private static attributes. var constants = { CLASS_NAME: 'Human', SOME_CONSTANT_1: 'Some value 1', SOME_CONSTANT_2: 'Some value 2' } // Privileged static method. this.getConstant(name) { return constants[name]; } // Return the constructor return function (newSurname, newName) { ... } })();
  • 16. Эмуляция классического наследования /* Class Person */ function Person(name) { this.name = name; } Person.prototype.getName = function() { return this.name; } /* Class Author */ function Author(name, books) { Person.call(this, name); // Call the superclass's constructor in the scope of this this.books = books; // Add an attribute to Author } Author.prototype = new Person(); // Set up the prototype chain Author.prototype.constructor = Author; // Set the constructor attribute to Author Author.prototype.getBooks = function() { // Add a method to Author return this.books; } var author1 = new Author('Jeff Six', ['Application Security for the Android Platform']); var author2 = new Author('Vandad Nahavandipoor', ['iOS 5 Programming Cookbook']);
  • 17. Эмуляция классического наследования. Функция extend function extend(subClass, superClass) { var F = function() {}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; subClass.superclass = superClass.prototype; if(superClass.prototype.constructor == Object.prototype.constructor) { superClass.prototype.constructor = superClass; } } /* Class Person */ function Person(name) { this.name = name; } Person.prototype.getName = function() { return this.name; } /* Class Author. */ function Author(name, books) { Author.superclass.constructor.call(this, name); this.books = books; } extend(Author, Person); Author.prototype.getBooks = function() { return this.books; }; var author1 = new Author('Jeff Six', ['Application Security for the Android Platform']); var author2 = new Author('Vandad Nahavandipoor', ['iOS 5 Programming Cookbook']);
  • 18. Инкапсуляция при эмуляции классического наследования ● В подклассе имеется доступ только к публичным и привилегированным членам родительского класса; ● Приватные члены родительского класса доступны в подклассах, а также извне только через привилегированные методы самого родительского класса; ● Если есть необходимость в protected членах, принято соглашение использовать подчеркивание, например var _myProtectedVar = null;
  • 19. Прототипное наследование /* Clone function */ function clone(object) { function F() {} F.prototype = object; return new F; } /* Person Prototype Object */ var Person = { name: 'default name', getName: function() { return this.name; } } /* Author Prototype Object */ var Author = clone(Person); Author.books = []; // Default value Author.getBooks = function() { return this.books; } var author1 = clone(Author); // Author-like object author1.name = 'Jeff Six'; author1.books = ['Application Security for the Android Platform']; var author2 = clone(Author); // Author-like object author2.name = 'Vandad Nahavandipoor'; author2.books = ['iOS 5 Programming Cookbook'];
  • 20. Mixin /* Augment function. */ function augment(receivingClass, givingClass) { for(var methodName in givingClass.prototype) { if(!receivingClass.prototype[methodName]) { receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } } } /* Regular class */ var Class1 = function() {}; Class1.prototype = { method1: function() {}, method2: function() {} } /* Mixin class */ var Class2 = function() {}; Class2.prototype = { mixinMethod1: function() { alert('mixinMethod1 called'); }, mixinMethod2: function() { alert('mixinMethod2 called'); } }; augment(Class1, Class2); var myObj = new Class1(); myObj.mixinMethod1();
  • 21. Singleton /* Basic Singleton. */ /* Singleton with Private Members */ var Singleton = { MyNamespace.Singleton = (function() { attribute1: true, attribute2: 10, // Private members method1: function() { var privateAttribute1 = false; ... var privateAttribute2 = [1, 2, 3]; }, function privateMethod1() { method2: function(arg) { ... ... } } function privateMethod2(args) { }; ... } return { // Public members publicAttribute1: true, publicAttribute2: 10, publicMethod1: function() { ... }, publicMethod2: function(args) { ... } }; })();
  • 22. "Ленивое" инстанцирование MyNamespace.Singleton = (function() { var instance; // All of the singleton code here function constructor() { var privateAttribute1 = false; function privateMethod1() { ... } return { publicAttribute1: true, publicMethod1: function() { ... } } } return { // Public members getInstance: function() { if(!instance) { instance = constructor(); } return instance; } } })(); MyNamespace.Singleton.getInstance().publicMethod1(); // Call singleton method
  • 23. Простая Фабрика var CarFactory = { createCar: function(model) { var car; switch(model) { case 'bmw': car = new BMW(); break; case 'ford': car = new Ford(); break; case 'ferrari': default: car = new Ferrari(); } Interface.ensureImplements(car, Car); return car; } };
  • 24. Фабричный метод - паттерн, порождающий классы /* CarShop class (abstract). */ var CarShop = function() {}; CarShop.prototype = { sellCar: function(model) { var car = this.createCar(model); car.prepare(); car.wash(); return car; }, createCar: function(model) { throw new Error('Unsupported operation on an abstract class'); } }; ● Используем абстрактный класс; ● Используем метод extend: extend(FordCarShop, CarShop); ● Используем при необходимости метод ensureImplements: Interface.ensureImplements (car, Car).
  • 25. Компоновщик. Пример использования - запоминание форм var contactForm = new CompositeForm('contact-form', 'POST', 'contact.php'); var nameFieldset = new CompositeFieldset('name-fieldset'); nameFieldset.add(new InputField('first-name', 'First Name')); nameFieldset.add(new InputField('last-name', 'Last Name')); contactForm.add(nameFieldset); var addressFieldset = new CompositeFieldset('address-fieldset'); addressFieldset.add(new InputField('address', 'Address')); addressFieldset.add(new InputField('city', 'City')); addressFieldset.add(new SelectField('state', 'State', stateArray)); contactForm.add(addressFieldset); contactForm.add(new TextareaField('comments', 'Comments')); body.appendChild(contactForm.getElement()); addEvent(window, 'unload', contactForm.save); addEvent(window, 'load', contactForm.restore); addEvent('save-button', 'click', nameFieldset.save); addEvent('restore-button', 'click', nameFieldset.restore);
  • 26. Декораторы функций Выглядит это так: function upperCaseDecorator(func) { return function() { return func.apply(this, arguments).toUpperCase(); } } Можно применять с пользой: var gCollection = new YMaps.GeoObjectCollection(); gCollection = new TimeProfiler(gCollection); // Декорируем все методы профайлером gCollection.add([ new YMaps.Placemark(new YMaps.GeoPoint(37.518234, 55.708937)), new YMaps.Placemark(new YMaps.GeoPoint(37.514146, 55.722294)), new YMaps.Placemark(new YMaps.GeoPoint(37.514146, 55.722225)), new YMaps.Placemark(new YMaps.GeoPoint(37.514146, 55.722236)) ]); gCollection.removeAll(); С помощью декоратора TimeProfiler, в консоли будет напечатано время выполнения методов add и removeAll.
  • 27. Тренируем внимание ● Расширение встроенных прототипов языка - зло; ● Не забываем писать var; ● Учитываем зависимость производительности от длины цепочек прототипов; ● Цикл for in проходит по всей цепочке прототипов. Решение - hasOwnProperty; ● JavaScript не резервирует свойство с именем hasOwnProperty, но можно делать так: ({}).hasOwnProperty.call(obj, 'propertyName'); ● Обходить обычный массив с помощью for in - зло; ● Ключевое слово this ссылается на контекст вызова, но его можно явно задать при call и apply; ● arguments не является наследником Array, у него нет push, pop, slice и т.д.; ● Помним про высасывание определений вверх ближайшей области видимости; ● Используем instanceof только собственных типов. Для стандартных типов - зло; ● eval - зло: а) безопасность; б) косвенный вызов и выход из локального scope; ● for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); } Числа 0-9 не будут напечатаны, так как анонимная функция сохраняет ссылку на переменную i, которая в момент вызова будет равна 10. Решение: for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i); }
  • 28. Сравниваем осторожно Оператор нестрогого равенства: Оператор строгого равенства: "" == "0" false "" === "0" false 0 == "" true 0 === "" false 0 == "0" true 0 === "0" false false == "false" false false === "false" false false == "0" true false === "0" false false == undefined false false === undefined false false == null false false === null false null == undefined true null === undefined false " trn" == 0 true " trn" === 0 false
  • 29. Внимание, оператор typeof Результат работы typeof (простите, но так исторически сложилось...): Значение [[Class]] = Object.prototype.toString. Тип call(myObj) "foo" String string new String("foo") String object 1.2 Number number new Number(1.2) Number object true Boolean boolean new Boolean(true) Boolean object new Date() Date object new Error() Error object [1,2,3] Array object new Array(1, 2, 3) Array object new Function("") Function function /abc/g RegExp object (function в Nitro/V8) new RegExp("meow") RegExp object (function в Nitro/V8) {} Object object new Object() Object object
  • 30. Почитать ● Pro JavaScript design patterns (Ross Harmes, Dustin Diaz); ● JavaScript Garden: http://shamansir.github.com/JavaScript-Garden/; ● MDN: https://developer.mozilla.org/en/JavaScript; ● http://javascript.ru/.