0

我有一些与原型有关的问题。

如果我们Dog通过Person函数构造函数创建了一个对象。SayPerson在每个实例成员上有 2 个属性。

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

现在我们已经创建了 10 个对象,比如Pug,Bulldog等等。

var Pug =new Dog('pug','white');
var Bulldog =new Dog('Bulldog','black');

现在突然我们想在Dog中添加一个属性,以便所有对象都可以访问它。我们可以通过两种方式做到这一点:

  1. 在函数构造函数中添加它this.leg : 4
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

或者

  1. 添加它使用
Dog.prototype.leg = 4;

现在我的问题是在这些变体中的每一个中,属性将被添加它的原型属性意味着作为原型成员而不是作为实例成员?为什么?

如果在创建对象后我们想要添加一些属性并且我们希望它作为实例成员添加意味着自己的属性我该怎么做?

我在浏览器控制台中得到什么:

Pug { name : 'pug',color :'white'}
_ proto_ : { leg :4 }

我所期待的:

Pug { name : 'pug',color :'white',leg :4 }
_proto_ :Object
4

2 回答 2

0

当你这样做时,Dog.prototype.leg = 4;你实际上是在修改原型本身。但是,未来实例化的对象将继承该新属性作为实例属性

内存中的现有实例在实例化时将继续使用预先存在的实例属性

var Dog = function (name,color){
    this.name =  name,
    this.color = color
};

console.log("Existing instances in memory");
let toy = new Dog("toy", "brown");
let tay = new Dog("tay", "grey");
console.log(toy, "\n", tay); // Existing instances in memory.

console.log("Future instance in memory.");
Dog.prototype.leg = 4;
let toe = new Dog("tay", "black");
console.log(toe); // Future instance in memory.
.as-console-wrapper { max-height: 100% !important; top: 0; }

于 2019-12-16T12:49:50.527 回答
0

使用选项 1 将在创建的每个新对象上附加一个实例属性:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

//overwrite the constructor function
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

var Dalmatian = new Dog('dalmatian', 'spotted');

//check the browser console as well
console.log(Dalmatian);
console.log(Dalmatian.leg)
console.log(Dalmatian.hasOwnProperty('leg'));

console.log(Bulldog);
console.log(Bulldog.leg)
console.log(Bulldog.hasOwnProperty('leg'));

既然如此,这意味着您将获得您期望的确切输出。但是,这仅适用于创建的任何对象实例——旧的对象实例不会被修改,如上所示。

使用选项 2 ,无论您何时完成修改,所有实例都将通过其原型访问属性:leg

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

//modify prototype
Dog.prototype.leg = 4;

var Dalmatian = new Dog('dalmatian', 'spotted');

//check the browser console as well
console.log(Dalmatian);
console.log(Dalmatian.leg)
console.log(Dalmatian.hasOwnProperty('leg'));

console.log(Bulldog);
console.log(Bulldog.leg)
console.log(Bulldog.hasOwnProperty('leg'));

因此,这将影响在更改之前创建的对象,但如果您希望这都是实例属性,那么这将不会发生 - 因为您可以看到.hasOwnProperty('leg')返回false,因为它们通过原型访问它。

如果您想修改Dog在某些更改之前和之后创建的所有对象 - 原型链是最简单的选择。但是,如果您想修改实例,则没有简单的方法可以做到。您可以重新创建所有对象:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

//overwrite the constructor function
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

var Dalmatian = new Dog('dalmatian', 'spotted');

//re-create
Pug = new Dog(Pug.name, Pug.color);
Bulldog = new Dog(Bulldog.name, Bulldog.color);

//check the browser console as well
console.log(Dalmatian);
console.log(Dalmatian.leg)
console.log(Dalmatian.hasOwnProperty('leg'));

console.log(Bulldog);
console.log(Bulldog.leg)
console.log(Bulldog.hasOwnProperty('leg'));

或修改它们:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

//overwrite the constructor function
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

var Dalmatian = new Dog('dalmatian', 'spotted');

//modify
Pug.leg = 4;
Bulldog.leg = 4;

//check the browser console as well
console.log(Dalmatian);
console.log(Dalmatian.leg)
console.log(Dalmatian.hasOwnProperty('leg'));

console.log(Bulldog);
console.log(Bulldog.leg)
console.log(Bulldog.hasOwnProperty('leg'));

无论哪种情况,您都需要引用所有旧对象。

选项 1 需要注意的最后一件事是,如果您更改 function,那么您将创建新Dog对象,但它们将 Dog以前不同,因为 function 现在不同:

var Dog = function (name,color){
   this.name =  name,
   this.color = color
};

var Pug = new Dog('pug','white');
var Bulldog = new Dog('Bulldog','black');

console.log("Bulldog is dog:", Bulldog instanceof Dog); //true - constructed with current Dog

//overwrite the constructor function - it's now *different*
var Dog = function (name,color){
    this.name =  name,
    this.color = color,
    this.leg = 4
};

var Dalmatian = new Dog('dalmatian', 'spotted');

console.log("Dalmatian is dog:", Dalmatian instanceof Dog); //true - constructed with  the new Dog

console.log("Bulldog is dog:", Bulldog instanceof Dog); //false - *not* constructed with the new Dog

如果这种差异很重要,那么您要么需要一种不同的方式来识别对象,要么重新创建它们。或者,原型更改将避免不匹配的构造函数,但同样,您不会获得实例属性。

于 2019-12-16T15:03:58.053 回答