Visão geral
Todos os objetos em JavaScript têm sua própria cadeia de herança. Ou seja, cada objeto herda outro objeto, chamado de objeto "protótipo". Exceto pelo NULL, ele não possui seu próprio objeto de protótipo.
A importância de um objeto de protótipo é que, se o objeto A for um protótipo do objeto B, o objeto B poderá obter todas as propriedades e métodos do objeto A. O objeto.GetPrototyPof é usado para obter o objeto protótipo do objeto atual.
var p = object.getProTypeOf (obj);
No código acima, o objeto P é o protótipo objeto do objeto obj.
O método Object.Create é usado para gerar um novo objeto e herdar o objeto especificado.
var obj = object.create (p);
No código acima, o protótipo do objeto OBJ recém -gerado é objeto p.
O atributo __proto__ não padrão (dois sublinhados na frente e atrás) pode reescrever o protótipo objeto de um determinado objeto. No entanto, você deve tentar usar essa propriedade o mínimo possível, mas use object.getPrototypeOf () e object.SetProTypeOf () para ler e gravar objetos de protótipo.
var obj = {}; var p = {}; obj .__ proto__ = p; object.getProTypeOf (obj) === p // trueO código acima define o objeto P como o protótipo do objeto OBJ através do atributo __proto__.
Aqui está um exemplo prático.
var a = {x: 1}; var b = {__proto__: a}; bx // 1No código acima, o objeto B define seu objeto de protótipo como um objeto através do atributo __proto__, para que o objeto B possa obter todas as propriedades e métodos do objeto a. O próprio objeto B não possui um atributo X, mas o mecanismo JavaScript encontra seu protótipo objeto A através do atributo __proto__ e depois lê o atributo x de a.
O novo comando cria um novo objeto de instância através de um construtor. Ele está essencialmente vinculando o protótipo do objeto de instância à propriedade do protótipo do construtor e, em seguida, executando o construtor no objeto de instância.
var o = new Foo (); // é equivalente a var o = new Object (); o .__ proto__ = foo.prototype; foo.call (o);
O atributo __proto__ do próprio objeto do protótipo também pode apontar para outros objetos, formando assim um nível de "cadeia de protótipo" por nível.
var a = {x: 1}; var b = {__proto__: a}; var c = {__proto__: b}; cx // 1Deve -se notar que procurar um determinado atributo na cadeia de protótipos tem um impacto no desempenho. Quanto maior o nível do objeto de protótipo que você está procurando, maior o impacto no desempenho. Se você procurar uma propriedade inexistente, ela atravessará toda a cadeia de protótipo.
Esta ação apontando
Não importa onde isso seja definido, quando usado, sempre aponta para o objeto atual, não o objeto de protótipo.
var o = {a: 2, m: function (b) {return this.a + 1; }}; var p = object.create (o); pa = 12; pm () // 13No código acima, o método M do objeto P vem de seu objeto de protótipo o. Neste momento, esse objeto dentro do método M não aponta para O, mas para p.
Herança de construtores
Esta seção apresenta como fazer um construtor herdar outro construtor.
Suponha que exista um construtor de forma.
função forma () {this.x = 0; this.y = 0;} shape.prototype.move = function (x, y) {this.x += x; this.y += y; console.info ('forma movida.');}; o construtor retângulo herda a forma. function retângulo () {shape.call (this); // Ligue para o construtor da classe pai} // Outra maneira de gravar a função Rectangle () {this.base = shape; this.base ();} // A subclasse herda o método da classe pai retângulo.prototype = object.create (shape.prototype); rect.prototype.constructor = retângulo; var ret = new Rectangn (); retângulo de retângulo // TrueCt IndefsOf Shape // Truerect.Move (1, 1, 1)O código acima mostra que a herança do construtor é dividida em duas partes, uma é que a subclasse chama o método do construtor da classe pai e o outro é que o protótipo da subclasse aponta para o protótipo da classe pai.
No código acima, a subclasse herda a classe pai como um todo. Às vezes, apenas a herança de um único método é necessário e o método de escrita a seguir pode ser usado.
Classb.prototype.print = function () {Classa.prototype.print.call (this); // Algum código}No código acima, o método de impressão da subclasse B chama primeiro o método de impressão da classe A dos pais e depois implanta seu próprio código. Isso é equivalente a herdar o método de impressão da classe pai A.
__proto__ atributo
O atributo __proto__ aponta para o objeto protótipo do objeto atual, ou seja, o atributo de protótipo do construtor.
var obj = new Object (); obj .__ proto__ === object.prototype // trueBJ .__ proto__ === obj.constructor.prototype // true
O código acima primeiro cria um novo objeto Obj, seu atributo __proto__, apontando para o atributo protótipo do construtor (objeto ou obj.constructor). Portanto, depois de comparar os dois, retorne verdadeiro.
Portanto, existem três maneiras de obter o objeto de protótipo do objeto de instância obj.
Entre os três métodos acima, os dois primeiros não são muito confiáveis. O mais recente ES6 padrão estipula que apenas o navegador precisa implantar o atributo __proto__ e outros ambientes podem não ser implantados. No entanto, obj.constructor.prototype pode falhar ao alterar manualmente o objeto de protótipo.
var p = function () {}; var p = new p (); var c = function () {}; c.prototype = p; var c = new c (); c.constructor.prototype === p // falseNo código acima, o objeto de protótipo do construtor C é alterado para P, e o resultado é que C.Constructor.Prototipo está distorcido. Portanto, ao alterar o objeto de protótipo, o atributo do construtor deve ser definido ao mesmo tempo.
C.prototype = p; c.prototype.Constructor = C; C.Constructor.Prototype === P // true
Portanto, é recomendável usar o terceiro objeto.GetProTypeOf do método para obter o objeto de protótipo. O uso desse método é o seguinte.
var o = new Object (); object.getPrototypeof (o) === Object.prototype // true
Você pode usar o método Object.getProTypeOf para verificar se o navegador suporta o atributo __proto__, que não é suportado por navegadores antigos.
Object.getPrototypeOf ({__proto__: null}) === nullO código acima define o atributo __Proto__ de um objeto para nulo e, em seguida, usa o método Object.getPrototyOf para obter o protótipo desse objeto para determinar se é igual a NULL. Se o ambiente atual suportar o atributo __proto__, o resultado da comparação dos dois deve ser verdadeiro.
Com o atributo __proto__, é fácil configurar o protótipo do objeto de instância. Suponha que haja três objetos: máquina, veículo e carro, onde a máquina é o protótipo de veículo e veículo é o protótipo de carro, que pode ser definido com apenas duas linhas de código.
veículo .__ proto__ = máquina; carro .__ proto__ = veículo;
O seguinte é um exemplo. As propriedades definidas no objeto de protótipo são lidas, respectivamente, através do atributo __proto__ e do atributo construtor.Prototipo.
Array.prototype.p = 'abc'; var a = new Array (); a .__ Proto __. P // abca.constructor.prototype.p // abc
Obviamente, __proto__ parece um pouco mais conciso.
Quando um objeto de instância é gerado através de um construtor, o atributo __proto__ do objeto de instância aponta automaticamente para o objeto protótipo do construtor.
var f = function () {}; var a = {}; f.prototype = a; var o = new f (); o .__ proto__ === a // trueHerança de atributos
Existem dois tipos de atributos. Um é o atributo nativo do próprio objeto, e o outro é o atributo herdado herdado do protótipo.
Propriedades nativas de um objeto
Todas as propriedades do objeto em si podem ser obtidas usando o método Object.TetownPropertyNames.
Object.getownPropertyNames (DATE) // ["Parse", "Argumentos", "UTC", "Caller", "Name", "Protótipo", "agora", "Length"]
Entre as propriedades do próprio objeto, algumas são enumeráveis (enumeráveis), enquanto outras não são enumeráveis. Somente obtenha as propriedades que podem ser enumeradas, use o método Object.Keys.
Object.Keys (DATE) // [] HASOWNPROPERTY ()
O método HasownProperty retorna um valor booleano para determinar se uma determinada propriedade é definida no próprio objeto ou na cadeia de protótipo.
DAT.HASOWNPROPERTY ('Length') // TrueDate.HasownProperty ('ToString') // falseO método HasownProperty é o único método em JavaScript que não atravessa a cadeia de protótipo ao processar as propriedades do objeto.
Propriedades de herança de um objeto
Objetos criados com o objeto.Create Método herdará as propriedades de todos os objetos de protótipo.
var proto = {p1: 123}; var o = object.create (proto); o.p1 // 123o.HasownProperty ("p1") // falseObtenha todos os atributos
Para determinar se um objeto possui uma determinada propriedade (seja sua ou herdada), use o operador no IN.
"Comprimento" em data // True "ToString" em data // true
Obtenha todas as propriedades enumeráveis de um objeto (seja ele próprio ou herdado) e você pode usar um loop for-in.
var o1 = {p1: 123}; var o2 = object.create (o1, {p2: {value: "abc", enumerável: true}}); para (p em o2) {console.info (p);} // p2 // p1Para obter as próprias propriedades do objeto no loop for ... em loop, você pode usar o método HasownProperty para julgar.
for (var nome em objeto) {if (object.HasownProperty (nome)) { / * Código de loop * /}}Para obter todas as propriedades do objeto (seja ele próprio ou herdado e se ele é enumerável), você pode usar a seguinte função.
função herditedpropertyNames (obj) {var props = {}; while (obj) {object.getownPropertyNames (obj) .ForEach (function (p) {props [p] = true;}); obj = object.getProTypeOf (obj); } Return Object.GetownPropertyNames (Props);}O uso é o seguinte:
herdedpropertyNames (data) // ["chamador", "construtor", "tostring", "utc", "ligue", "parse", "protótipo", "__defineSetter__", "__lookupSetter__", "comprimento" ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ", o", o ", o", ",", ",", ",", ", o", o lengtet ", o", o lengtyOt, o ", o", ",", ",", ",", ",", ", o", o cenário do portão ", o cenário", o topo do que o e o objetivo do ser que o devedor do que o ateso. "PropertyIsEnumerable", "Valueof", "Apply", "__definegetter__", "Name", "agora", "HasownProperty"]
Cópia do objeto
Se você deseja copiar um objeto, precisa fazer as duas coisas a seguir.
Verifique se o objeto copiado possui o mesmo objeto de protótipo que o objeto original.
Verifique se o objeto copiado possui as mesmas propriedades que o objeto original.
A seguir, a função de copiar o objeto escrito com base nos dois pontos acima.
função copyObject (orig) {var cópia = object.create (object.getPrototypeof (orig)); CopyOwnPropertiesFrom (cópia, orig); Return copy;} função copyOwnPropertiesFrom (Target, Source) {object .GetownPropertyNames (Origem) .ForEach (functy (propKey) {var desct = object.GetownPropertyDescriptor (fonte, propKey); object.DefineProperty (Target, descrito, desc);}); alvo de retorno;}Herança múltipla
O JavaScript não fornece várias funções de herança, ou seja, não permite um objeto para herdar vários objetos ao mesmo tempo. No entanto, essa função pode ser alcançada através de soluções alternativas.
função m1 (prop) {this.hello = prop;} função m2 (prop) {this.world = prop;} função s (p1, p2) {this.base1 = m1; this.base1 (p1); this.base2 = m2; this.base2 (p2);} s.prototype = new M1 (); var s = novo S (111, 222); S.Hello // 111s.world // 222No código acima, a subclasse s herda as classes parentais M1 e M2. Obviamente, da perspectiva da cadeia de herança, S possui apenas uma classe pai M1, mas, desde a instância de S, os construtores de M1 e M2 são executados ao mesmo tempo, herda os métodos dessas duas classes ao mesmo tempo.