HTML5 [1]
CSS3 [1]
JavaScript [3]
JS in HTML5 [4]
Canvas (Context2D) [1]
Canvas (WebGL) [0]
Browser Technologies [2]
jQuery [1]
ExtJS [0]
Prototype.js [2]
SVG [2]
Browsers [2]
Mozilla Plugins [0]
XUL, Jetpack, etc.
Web [2]
MeowW [4]
iOS [0]
Алгоритмы [0]
Криптография [0]
Теория игр [0]
Теория вероятностей [0]
Математика [1]
Мат. анализ [0]
Алгебра [0]
Дискретная математика [0]
Теория графов [0]
Комбинаторика [0]
Теория чисел [0]
Комплексный анализ [0]
Матлогика [0]
Математическая логика, её связь с теорией алгоритмов и т.п.
Тензоры [0]
Геометрия [0]
Топология [0]
Дифференциальная геометрия [0]
Дифференциальные уравнения [0]
09 Июня 2011 в 07:58:15
16:38:41
ECMAScript 5 - новые возможности объектов

ECMAScript

Привет). Сегодня мы поговорим про такую штуку, как ECMAScript. Не сомневаясь в ваших знаниях (ага, конечно!), на всякий случай напомню: когда компания Netscape придумала JavaScript, она обратилась к ECMA - чтобы те стандартизировали язык. В результате он получил название ECMAScript. Однако под именем JavaScript он прижился больше. Когда же его называют ECMAScript - значит, говорим про премудрости программирования на нём, про то что написано в стандартах и т.д.

Возможно, вы слышали про JavaScript 2.0. Ну или ECMAScript 5 - кому как нравится. Чаще его называют последним названием: ведь речь идёт о стандарте. Да, это новый стандарт любимого JS. О нём мы сегодня и поговорим.

Объекты

Сегодня мы будем рассматривать главным образом объекты и их свойства. Итак, существуют два типа свойств объекта - это обычные data-свойства и accessor-свойства.

Работа со свойствами

Для работы со свойствами в JavaScript появился целый ворох функций для объектов. Смотрим:

  • Object.defineProperty(object, property, parameters) - получение или изменение свойства у нашего объекта.
  • var obj = {};
    Object.defineProperty(obj, "prop", {
     /* здесь дополнительные параметры свойства, об это позже */
    });
  • Object.defineProperties(...) - то же самое, но сразу с несколькими свойствами.
  • Object.getOwnPropertyDescriptor(property) - получение дескриптора свойства.
  • Object.keys(object) - список свойств объекта (только с параметром enumerable).
  • Object.getOwnPropertyNames(object) - все "родные" свойства (объявленные в объекте, а не наследуемые).
  • Object.preventExtensions(object) - запретить расширять объект.
  • Object.isExtensible(object) - можно ли расширять объект.
  • Object.seal(property) - "опечатать" объект (запретить удалять свойства).
  • Object.isSealed(property) - "опечатан" ли объект?
  • Object.freeze(property) - "заморозить" объект (запретить изменять свойства).
  • Object.isFrozen(property) - "заморожен" ли объект?
  • Object.getPrototypeOf(object) - получение прототипа объекта (возвращает object.prototype).
  • Object.create(parent, object) - создаёт и возвращает новый объект, наследующий свойства от объекта parent.

Data-свойства

Что за звери эти data-свойства? Это наши привычные свойства из JS 1.5. Просто теперь они называются data-свойствами (свойства данных, простые свойства для сохранения данных) - чтобы как-то отличать их от accessor-свойств. И ещё у них появились специальные параметры - их можно указывать последним параметром, создавая через функцию Object.defineProperty (или defineProperties). Свойства такие:

  • value - значение свойства.
  • writable - если false, то только чтение.
  • enumerable - перечислимо в for-in?
  • configurable - удаляется?
var obj = {};
Object.defineProperty(obj, 'test', {
 value:10,
 writable:true,
 enumerable:true,
 configurable:true
});
// такая запись эквивалентна записи ECMAScript 3:
obj.test=10;
alert(obj.test); // 10

В ECMAScript 5 стало возможным создавать константы не как переменные, а специальным оператором. Точно так же можно записать константу вот так:

var obj = {};
Object.defineProperty(obj, 'MY_CONST', {
 value:'test',
 writable:false,
 enumerable:false,
 configurable:false
});

А ещё мы можем не создавать объект заранее, а затем расширять, как мы это делали раньше, а создать прямо (ведь функция возвращает изменённый объект):

var obj = Object.defineProperty({}, 'myTestValue', {
 value:'test',
 writable:true,
 enumerable:true,
 configurable:false
});

Accessors

Accessor-свойства (от англ. Access - доступ) - специальные свойства, которые работают малость по-другому, чем обычные. Их тоже можно создать через defineProperty. Они тоже имеют свойства enumerable и configurable, означающие то же самое, но вместо свойств value и writable, у нас есть функции: get и set. Когда мы пытаемся прочитать accessor-свойство, выполняется функция get, а возвращаемое функцией значение передаётся коду как значение свойства. Точно так же мы пытаемся изменить переменную - работает функция set. Вот пример:

var o = {};
Object.defineProperty(o, 'testAccessor', {
 get : function(){
 return this.y;
 // при попытке чтения мы возвращаем внешнюю переменную y
 },
 set : function(){
 this.y++;
 // при записи мы игнорируем значение, которое пытаются записать и увеличиваем y на 1
 },
 // если забыть функцию set, то свойство будет недоступно для записи
 enumerable:true, // пусть можно перечислять: нам не жалко
 configurable:true // и удалять
});
o.testAccessor; // 0
o.testAccessor=120; // присваиваем
o.testAccessor; // 1

Мы можем также сделать вот так:

var o = {
 x:10,
 y:20,
 get z(){
 return this.x+this.y;
 }
};
o.z; // возвратит 30

Получаем дескриптор

Вопрос: вот мы сделали свойство объекту... А как потом узнать его параметры? Writable, configurable, enumerable? Как узнать значения этих свойств? Здесь нам поможет функция:

  • Object.getOwnPropertyDescriptor(obj, param) - возвращает дескриптор объекта.

Дескриптор - это такой специальный объект, который содержит свойства объекта. В общем, вот пример:

var o = Object.defineProperty({}, 'z', {
 value:10,
 writable:true,
 enumerable:false,
 configurable:true
});
o.z; // 10

var desc=Object.getOwnPropertyDescriptor(o, 'z');
desc.writable; // true
desc.enumerable; // false
desc.configurable; // true

Список свойств объекта

Мы можем легко получить список свойств объекта с помощью двух функций:

  • Object.keys(obj) - возвращает все свойства объекта с enumerable:true
  • Object.getOwnPropertyNames(obj) - возвращает вообще все родные свойства объекта (не только enumerable).

Эти функции возвращают массив с именами свойств объекта. Вот вам пример:

var o = {
 x : 10,
 y : 20
};

Object.defineProperty(o, 'z', {
 value:30,
 writable:true,
 enumerable:false,
 configurable:false
});
Object.keys(o); // ['x', 'y']
Object.getOwnPropertyNames(o); // ['x', 'y', 'z']

Фиксируем объект

В новом JS есть несколько функций для различных фиксаций, опечатываний и заморозок объекта. Вот:

Статика: запрещаем расширение
  • Object.isExtensible(obj) - статичен ли объект?
  • Object.preventExtensions(obj) - сделать объект статичным (запрещать добавлять новые свойства).
var o = {
 x:10,
 y:20
};
Object.isExtensible(o); // true
Object.preventExtensions(o);
Object.isExtensible(o); // false
o.z=30; // false
o.z; // undefined
Опечатывание: запрещаем удаление
  • Object.isSealed(obj) - опечатан ли объект?
  • Object.seal(obj) - опечатать объект (запретить удалять свойства). Примечание: всем устанавливается configurable="false".
var o = {
 x:10,
 y:20
};
Object.isSealed(o); // false
Object.seal(o);
Object.isSealed(o); // true
Object.getOwnPropertyDescriptor(o, 'x').configurable; // false
Заморозка: запрещаем изменение
  • Object.isFrozen(obj) - заморожен ли объект?
  • Object.freeze(obj) - заморозить объект (запретить изменять свойства). Примечание: всем устанавливается writable="false".
var o = {
 x:10,
 y:20
};
Object.isFrozen(o); // false
Object.freeze(o);
Object.isFrozen(o); // true
Object.getOwnPropertyDescriptor(o, 'x').writable; // false

Прототипы

Осталось кое-что интересное на закуску. Это прототипы.

  • Object.getPrototypeOf(obj) - возвращает прототип объекта. Равен (==) и идентичен (===) obj.prototype.
  • Object.create(parent, obj) - создаёт и возвращает новый объект, наследующий все свойства объекта parent. Похоже на $.extend из jQuery.
var o = {
 x : 10,
 y : 20
};
var o2 = Object.create(o, {
 z : 30
});
o2.x; // 10
o2.y; // 20
o2.z; // 30

Одна интересная вещь. Если мы попытаемся унаследовать от null, объект не будет наследоваться даже от Object, как обычно бывает при создании объекта.

var o = Object.create(null);
alert(o); // error
// нет метода toString (обычно наследуемого от объекта), используемого alert-ом

Под конец...

Вообще появляется впечатление, что ECMA просто нечего делать. Конечно многие изменения хорошие и полезные, но чётко всё структурировать... Это становится похоже на XHTML, вернее на его худшие части. Нет, чтобы улучшить логику, убрать проблемные места... Оператор typeof на худой случай поправить: чтобы говорил, что строка - это не только '...', но и new String (и то же с Number и Boolean), чтобы опознавал Array, Date и Error (и RegExp забыл)... А я ещё в ECMAScript 6 заглянул: если нигде не ошибся, то там удавиться можно: локальное присваивание придумали. Хотя я наверняка ошибся.
И JavaScript всё удаляется от своего прародителя - языка C. Хотя в некоторых местах и приближается к C++.

Просмотров: 2463 | | Теги: объект, object, прототип, ecmascript 5, PROTOTYPE, property, javascript 2
Всего комментариев: 1
1 Кейтен (12 Июня 2011 16:18:21) 0  
P.S. Будет продолжение про ECMAScript 5 и 6
Спам
Материал |
Имя *:
Email:
Код *: