Por que não usaria Child.prototype = Parent.Prototype em vez de Child.prototype = new Parent (); para inheritance de Javascript?

Eu não entendo esse comportamento em javascript para inheritance que eu sempre vi definido assim:

function GameObject(oImg, x, y) { this.x = x; this.y = y; this.img = oImg; this.hit = new Object(); this.hitBox.x = x; this.hitBox.y = y; this.hitBox.width = oImg.width; this.hitBox.height = oImg.height; } Spaceship.prototype = new GameObject(); Spaceship.prototype.constructor = Spaceship; function Spaceship(){ console.log("instantiate ship"); GameObject.apply(this, arguments); this.vx = 0; this.vy = 0; this.speed = 3; this.friction = 0.94; } 

Mas no meu caso, estas linhas:

  this.hitBox.width = oImg.width; this.hitBox.height = oImg.height; 

Quando eu faço um console.log (this) no meu construtor Spaceship, eu posso ver que a propriedade proto é definida como Spaceship em vez de GameObject, se eu removê-los, é definido como GameObject.

E se eu usar:

  Spaceship.prototype = GameObject.prototype; 

Eu não tenho mais problemas com isso. A razão que isso me bloqueia é que eu tenho outro object com um método add () e ele verifica que o object indefinição de GameObject com este código:

  if(object instanceof GameObject) 

Eu não entendo o que essas duas linhas provavelmente podem mudar para que a inheritance seja quebrada quando elas estiverem presentes e eu não estou certo de fazer inheritance, a segunda maneira é boa. Alguém poderia me esclarecer sobre isso, por favor? 🙂

Se você fizer

Spaceship.prototype = GameObject.prototype;

Então ambos se referem ao mesmo object, então você pode ter tudo no GameObject , se você adicionar algo ao Spaceship.prototype , ele será adicionado ao GameObject.prototype também. Você pode facilmente testá-lo adicionando algo ao Spaceship.prototype após a atribuição. Por exemplo, no seu caso você pode ver que GameObject.prototype.constructor é na verdade Spaceship .

Quanto a

 Spaceship.prototype = new GameObject(); 

Isso invoca o construtor que pode ter efeitos colaterais indesejados, você prefere usar:

 Spaceship.prototype = Object.create(GameObject.prototype); 

Onde a funcionalidade Object.create usada aqui se resume a:

 Object.create = function( proto ) { function f(){} f.prototype = proto; return new f; }; 

Os navegadores modernos já têm a function.

Nunca foi explicado corretamente por que você estava tendo um comportamento estranho com this.hitBox (acho que é o que você estava tentando dizer).

Se você fizer inheritance invocando o construtor do pai para criar um protótipo, o construtor desse pai será executado uma vez para criar uma instância do tipo pai e todas as instâncias do tipo filho compartilharão essa instância como seu protótipo.

O problema com isso é que, se esse construtor tiver quaisquer linhas que atribuam objects mutáveis ​​a this , esses objects serão propriedades nesse protótipo e quaisquer modificações nesses objects serão refletidas em todas as instâncias do tipo filho:

 Spaceship.prototype = new GameObject(); Spaceship.prototype.constructor = Spaceship; var sps1 = new Spaceship(); var sps2 = new Spaceship(); sps1.hitBox.x = 9; sps2.hitBox.x = 12; console.log(sps1.hitBox.x); // 12 (oh noes! what happened) console.log(sps2.hitBox.x); // 12 

(há outros problemas similares com a abordagem “chamar um construtor para fazer um protótipo”, mas vou deixar aqui nesse ponto)

@ Sugestão de Esailija para usar Object.create(baseObject) é o primeiro passo para resolver este problema. Ele cria um novo object cujo protótipo é baseObject , mas sem o material que está configurado no construtor (isso é bom, mas precisa ser contabilizado. Continue lendo …).

Como acabei de dizer, isso criará um object onde a lógica de boot no construtor do pai nunca foi executada, mas na maioria dos casos essa lógica é relevante para a funcionalidade do object. Portanto, há mais uma coisa que você precisa fazer, que é fazer com que o construtor filho chame o construtor pai:

 function Spaceship(oImg, x, y) { // call parent constructor on this object and pass in arguments. // you could also use default values for the arguments when applicable GameObject.call(this, oImg, x, y); // remainder of Spaceship constructor... } 

Isso garantirá que a lógica do construtor pai seja executada separadamente para cada nova Spaceship e execute as tarefas de boot necessárias.

 function GameObject(oImg, x, y) { this.x = x; this.y = y; this.img = oImg || {width:null, height: null}; this.hitBox = new Object(); this.hitBox.x = x; this.hitBox.y = y; this.hitBox.width = this.img.width; this.hitBox.height = this.img.height; } function Spaceship(){ GameObject.apply(this, arguments); this.vx = 0; this.vy = 0; this.speed = 3; this.friction = 0.94; } Spaceship.prototype = new GameObject(); var sps1 = new Spaceship(); var sps2 = new Spaceship(); sps1.hitBox.x = 9; sps2.hitBox.x = 12; console.log(sps1.hitBox.x); // 9 console.log(sps2.hitBox.x); // 12