Object.setPrototypeOf()

Это экспериментальная технология, часть предложения Harmony (ECMAScript 6).
Поскольку спецификация этой технологии ещё не стабилизировалась, проверьте таблицу совместимости её использования в различных браузерах. Также обратите внимание, что синтаксис и поведение экспериментальной технологии могут быть изменены в будущих версиях браузеров в соответствии с изменениями в спецификации.

Предупреждение: Изменение прототипа [[Prototype]] объекта является, по самой природе оптимизации доступа к свойствам в современных движках JavaScript, очень медленной операцией, это справедливо для любого браузера и движка JavaScript. Изменение прототипов очень тонко и обширно влияет на производительность, причём это влияние не ограничивается просто временем, проведённым внутри метода Object.setPrototypeOf(), оно может распространяться на любой код, который имеет доступ к любому объекту, чей прототип [[Prototype]] был изменён. Если вы заботитесь о производительности, вы никогда не должны изменять прототип [[Prototype]] объекта. Вместо этого создайте объект с нужным прототипом [[Prototype]], с помощью метода Object.create().

Сводка

Метод Object.setPrototype() устанавливает прототип (то есть, внутреннее свойство [[Prototype]]) указанного объекта в другой объект или null.

Синтаксис

Object.setPrototypeOf(obj, prototype);

Параметры

obj
Объект, которому устанавливается прототип.
prototype
Новый прототип объекта (объект или null).

Описание

Выкидывает исключение TypeError, если объект, чей прототип [[Prototype]] является не расширяемым, согласно методу Object.isExtensible(). Не делает ничего, если параметр prototype не является объектом или значением null (то есть, является числом, строкой, логическим значением или undefined). В противном случае метод устанавливает прототип [[Prototype]] объекта obj в новое значение.

Примеры

var dict = Object.setPrototypeOf({}, null);

Полифилл

Используя старое свойство Object.prototype.__proto__, мы можем легко определить Object.setPrototypeOf(), если он ещё не доступен:

Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
  obj.__proto__ = proto;
  return obj; 
}

Добавление цепочки прототипов

Сочетание метода Object.getPrototypeOf() и свойства Object.prototype.__proto__ позволяет добавить целую цепочку прототипов к новому прототипу объекта:

/**
*** Object.appendChain(@object, @prototype)
*
* Присоединяет первый неродной прототип цепочки к новому прототипу.
* Возвращает @object (если он был примитивным значением, оно будет преобразовано в объект).
*
*** Object.appendChain(@object [, "@arg_name_1", "@arg_name_2", "@arg_name_3", "..."], "@function_body")
*** Object.appendChain(@object [, "@arg_name_1, @arg_name_2, @arg_name_3, ..."], "@function_body")
*
* Присоединяет первый не родной прототип цепочки к родному объекту Function.prototype, затем присоединяет
* new Function(["@arg"(s)], "@function_body") к этой цепочке.
* Возвращает функцию.
*
**/

Object.appendChain = function(oChain, oProto) {
  if (arguments.length < 2) { 
    throw new TypeError('Object.appendChain - Not enough arguments');
  }
  if (typeof oProto === 'number' || typeof oProto === 'boolean') {
    throw new TypeError('second argument to Object.appendChain must be an object or a string');
  }

  var oNewProto = oProto,
      oReturn = o2nd = oLast = oChain instanceof this ? oChain : new oChain.constructor(oChain);

  for (var o1st = this.getPrototypeOf(o2nd);
    o1st !== Object.prototype && o1st !== Function.prototype;
    o1st = this.getPrototypeOf(o2nd)
  ) {
    o2nd = o1st;
  }

  if (oProto.constructor === String) {
    oNewProto = Function.prototype;
    oReturn = Function.apply(null, Array.prototype.slice.call(arguments, 1));
    this.setPrototypeOf(oReturn, oLast);
  }

  this.setPrototypeOf(o2nd, oNewProto);
  return oReturn;
}

Использование

Первый пример: присоединение цепочки к прототипу

function Mammal() {
  this.isMammal = 'да';
}

function MammalSpecies(sMammalSpecies) {
  this.species = sMammalSpecies;
}

MammalSpecies.prototype = new Mammal();
MammalSpecies.prototype.constructor = MammalSpecies;

var oCat = new MammalSpecies('Felis');

alert(oCat.isMammal); // 'да'

function Animal() {
  this.breathing = 'да';
}

Object.appendChain(oCat, new Animal());

alert(oCat.breathing); // 'да'

Второй пример: преобразование примитивного значения в экземпляр его конструктора и присоединение его цепочки к прототипу

function Symbol() {
  this.isSymbol = 'да';
}

var nPrime = 17;

alert(typeof nPrime); // 'number'

var oPrime = Object.appendChain(nPrime, new Symbol());

alert(oPrime); // '17'
alert(oPrime.isSymbol); // 'да'
alert(typeof oPrime); // 'object'

Третий пример: присоединение цепочки к объекту Function.prototype и новой функции к этой цепочке

function Person(sName) {
  this.identity = sName;
}

var george = Object.appendChain(new Person('Георг'),
                                'alert("Привет, парни!!");');

alert(george.identity); // 'Георг'
george(); // 'Привет, парни!!'

Спецификации

Спецификация Статус Комментарии
ECMAScript 6 (ECMA-262)
Определение 'Object.setProtoypeOf' в этой спецификации.
Кандидат в рекомендации Изначальное определение.

Совместимость с браузерами

Возможность Chrome Firefox (Gecko) Internet Explorer Opera Safari
Базовая поддержка 34
Смотрите Замечание 2675
31 (31)
Смотрите ошибка 885788
11 (Да) Нет
Возможность Android Chrome для Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Базовая поддержка Нет Нет 31.0 (31)
Смотрите ошибка 885788
(Да) Нет Нет

Смотрите также

Метки документа и участники

 Внесли вклад в эту страницу: Mingun
 Обновлялась последний раз: Mingun,