Обзор
Все объекты в JavaScript имеют свою собственную цепочку наследования. То есть каждый объект наследует другой объект, который называется объектом «прототип». За исключением нулевого, у него нет собственного объекта прототипа.
Важность прототипа объекта заключается в том, что если объект A является прототипом объекта B, объект B может получить все свойства и методы объекта A. Способ object.getPrototypof используется для получения объекта прототипа текущего объекта.
var p = object.getPrototypeof (obj);
В приведенном выше коде объект P является прототипом объектом объекта obj.
Метод Object.Create используется для генерации нового объекта и наследования указанного объекта.
var obj = object.create (p);
В приведенном выше коде прототип недавно сгенерированного объекта OBJ является объектом p.
Нестандартный атрибут __proto__ (два подчеркивания впереди и сзади) может переписать объект прототипа определенного объекта. Тем не менее, вы должны попытаться использовать это свойство как можно меньше, но использовать object.getprototypeof () и object.setprototypeof () для чтения и записи объектов прототипа.
var obj = {}; var p = {}; obj .__ Proto__ = p; object.getPrototypeof (obj) === p // trueПриведенный выше код устанавливает объект P как прототип объекта OBJ через атрибут __proto__.
Вот практическое пример.
var a = {x: 1}; var b = {__proto__: a}; bx // 1В приведенном выше коде объект B устанавливает свой объект прототипа в качестве объекта через атрибут __proto__, поэтому объект B может получить все свойства и методы объекта a. Сам объект B не имеет атрибута X, но двигатель JavaScript находит свой прототип объекта A через атрибут __proto__, а затем читает атрибут x a.
Новая команда создает новый объект экземпляра через конструктор. По сути, он связывает прототип объекта экземпляра с свойством прототипа конструктора, а затем выполнение конструктора на объекте экземпляра.
var o = new foo (); // эквивалентно var o = new Object (); o .__ Proto__ = foo.prototype; foo.call (o);
Собственный атрибут объекта Prototype __proto__ также может указывать на другие объекты, тем самым формируя уровень «цепочка прототипа» по уровню.
var a = {x: 1}; var b = {__proto__: a}; var c = {__proto__: b}; cx // 1Следует отметить, что поиск определенного атрибута в цепочке прототипа оказывает влияние на производительность. Чем выше уровень объекта прототипа, который вы ищете, тем больше влияние на производительность. Если вы ищете несуществующее свойство, оно пройдет всю цепь прототипа.
Это действие указывает
Независимо от того, где это определено, при использовании, он всегда указывает на текущий объект, а не на объект прототипа.
var o = {a: 2, m: function (b) {return this.a + 1; }}; var p = object.create (o); pa = 12; pm () // 13В приведенном выше коде метод m объекта P происходит из его прототипа объекта o. В это время этот объект внутри метода М. указывает не на O, а на P.
Наследование конструкторов
Этот раздел представляет, как сделать один конструктор унаследовать другого конструктора.
Предположим, есть конструктор формы.
function shape () {this.x = 0; this.y = 0;} shape.prototype.move = function (x, y) {this.x += x; this.y += y; console.info ('форма перемещена.');}; конструктор прямоугольника наследует форма. function rectangle () {shape.call (this); // Вызовите конструктор родительского класса} // Еще один способ написать функцию rectangle () {this.base = shape; this.base ();} // Подкласс наследует метод родительского класса rectangle.prototype = object.create (shape.prototype); rect.prototype.constructor = rectangle; var rect = rectangle (); прямоугольный экземпляр прямоугольника //Приведенный выше код показывает, что наследование конструктора делится на две части, одна из них заключается в том, что подкласс называет метод конструктора родительского класса, а другая заключается в том, что прототип подкласса указывает на прототип родительского класса.
В приведенном выше коде подкласс наследует родительский класс в целом. Иногда требуется только наследство одного метода, и можно использовать следующий метод написания.
Classb.prototype.print = function () {classa.prototype.print.call (this); // какой -то код}В приведенном выше коде метод печати подкласса B сначала вызывает метод печати родительского класса А, а затем развертывает свой собственный код. Это эквивалентно унаследованию метода печати родительского класса А.
__proto__ Атрибут
Атрибут __proto__ указывает на объект прототипа текущего объекта, то есть атрибут прототипа конструктора.
var obj = new Object (); obj .__ Proto__ === Object.prototype // trueObj .__ Proto__ === obj.constructor.prototype // true
Приведенный выше код сначала создает новый объект obj, его атрибут __proto__, указывающий на атрибут прототипа конструктора (объект или obj.constructor). Поэтому, сравнивая их, верните True.
Следовательно, существует три способа получить объект прототипа объекта экземпляра obj.
Среди трех вышеупомянутых методов первые два не очень надежны. Последний стандарт ES6 предусматривает, что только браузер должен развернуть атрибут __proto__, а другие среды не могут быть развернуты. Тем не менее, obj.constructor.protototype может потерпеть неудачу при вручную изменять объект прототипа.
var p = function () {}; var p = new p (); var c = function () {}; c.prototype = p; var c = new c (); c.constructor.prototype === p // falseВ приведенном выше коде объект прототипа конструктора C изменяется на P, и результатом является то, что C.Constructor.Prototype искажен. Поэтому при изменении объекта прототипа атрибут конструктора должен быть установлен одновременно.
C.Prototype = P; C.Prototype.Constructor = C; C.Constructor.Prototype === P // true
Следовательно, рекомендуется использовать метод третьего объекта. Использование этого метода заключается в следующем.
var o = new object (); object.getPrototypeof (o) === object.prototype // true
Вы можете использовать метод object.getPrototypeof, чтобы проверить, поддерживает ли браузер атрибут __proto__, который не поддерживается старыми браузерами.
Object.getPrototypeof ({__proto__: null}) === nullПриведенный выше код устанавливает атрибут __proto__ объекта в NULL, а затем использует метод object.getPrototypOF для получения прототипа этого объекта, чтобы определить, равно ли он нулевым. Если текущая среда поддерживает атрибут __proto__, результат сравнения этих двух должен быть правдой.
С атрибутом __proto__ легко настроить прототип объекта экземпляра. Предположим, есть три объекта: машина, автомобиль и автомобиль, где машина является прототипом транспортного средства, а транспортное средство - это прототип автомобиля, который можно установить только с двумя линиями кода.
автомобиль .__ Proto__ = машина; автомобиль .__ Proto__ = транспортное средство;
Ниже приведен пример. Свойства, определенные на объекте прототипа, считываются соответственно через атрибут __proto__ и атрибут конструктора.
Array.prototype.p = 'abc'; var a = new Array (); a .__ Proto __. P // abca.constructor.prototype.p // abc
Очевидно, __proto__ выглядит немного более лаконично.
Когда объект экземпляра генерируется через конструктор, атрибут __proto__ объекта экземпляра автоматически указывает на объект прототипа конструктора.
var f = function () {}; var a = {}; f.prototype = a; var o = new f (); o .__ proto__ === a // trueНаследство атрибутов
Есть два типа атрибутов. Один из них является нативным атрибутом самого объекта, а другой - унаследованный атрибут, унаследованный от прототипа.
Нативные свойства объекта
Все свойства самого объекта могут быть получены с использованием метода object.getownPropertyNames.
Object.getOwnPropertyNames (date) // [«parse», «аргументы», «utc», «caller», «имя», «прототип», «сейчас», «длина»]
Среди свойств самого объекта некоторые являются перечисленными (перечисляемыми), в то время как другие не являются перечисленными. Получите только те свойства, которые могут быть перечислены, используйте метод object.keys.
Object.keys (date) // [] hasownproperty ()
Метод HasownProperty возвращает логическое значение, чтобы определить, определяется ли определенное свойство на самом объекте или на цепочке прототипа.
Date.hashownproperty ('длина') // truedate.hasownproperty ('tostring') // falseМетод HasownProperty является единственным методом в JavaScript, который не проходит цепочку прототипа при обработке свойств объекта.
Наследние объекта объекта
Объекты, созданные с помощью метода Object.create, будут наследовать свойства всех объектов прототипа.
var proto = {p1: 123}; var O = objПолучите все атрибуты
Чтобы определить, имеет ли объект определенное свойство (является ли он своим собственным или унаследованным), используйте оператор.
«Длина» в дате // true »toString» в дате // true
Получите все перечисляемые свойства объекта (будь то собственный или унаследованный), и вы можете использовать цикл для вторжения.
var o1 = {p1: 123}; var o2 = objЧтобы получить собственные свойства объекта в для ... в цикле, вы можете использовать метод HasownProperty для суждения.
for (var name in object) {if (object.hasownproperty (name)) { / * code * /}}Чтобы получить все свойства объекта (независимо от того, является ли он собственным или унаследованным, и является ли он перечисленным), вы можете использовать следующую функцию.
Функция унаследована propertynames (obj) {var props = {}; while (obj) {object.getownpropertynames (obj) .foreach (function (p) {props [p] = true;}); obj = object.getPrototypeof (obj); } return object.getownPropertyNames (ops);}Использование выглядит следующим образом:
Унаследованные PropertyNames (Date) // [«Caller», «Constructor», «ToString», «UTC», «Call», «parse», «Прототип», «__definesetter__», «__lookupsetter__», «длина», «аргументы», «привязать», «__lookupgetter__», «volestroptipringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEringEr «ProperateSeNumerable», «ValueOf», «Apply», «__definegetter__», «Имя», «Сейчас», «HasownProperty»]
Копия объекта
Если вы хотите скопировать объект, вам нужно сделать следующие две вещи.
Убедитесь, что скопированный объект имеет тот же объект прототипа, что и исходный объект.
Убедитесь, что скопированный объект обладает теми же свойствами, что и исходный объект.
Ниже приводится функция копирования объекта, написанного на основе двух вышеуказанных точек.
Функция copyObject (orig) {var copy = object.create (object.getPrototypeof (orig)); CopyOwnPropertiesfrom (Copy, Orig); return Copy;} функция CopyOwnPropertiesFrom (Target, Source) {object .getOwnPropertyNames (Source) .Foreach (function (propkey) {var desc = object.getOwnPropertyDescriptor (источник, propkey); object.defineproperty (target, propkey, desc);}); вернуть цель;}Множественное наследство
JavaScript не предоставляет множественные функции наследования, то есть он не позволяет одному объекту наследовать несколько объектов одновременно. Однако эта функция может быть достигнута с помощью обходных путей.
функция m1 (prop) {this.hello = prop;} function m2 (prop) {this.world = prop;} function s (p1, p2) {this.base1 = m1; this.base1 (p1); this.base2 = m2; this.base2 (p2);} s.prototype = new m1 (); var s = new s (111, 222); s.hello // 111s.world // 222В приведенном выше коде подкласс S наследует как родительские классы M1, так и M2. Конечно, с точки зрения цепочки наследования S имеет только один родительский класс M1, но, поскольку в случае S конструкторы M1 и M2 выполняются одновременно, он унаследовал методы этих двух классов одновременно.