这可能是一个古老的问题,但我仍然无法理解它背后的理论。
我们有
function Test(name) {
this.name = name;
}
Test.prototype.myArray = []; // I know if i move this to constructor it can resolve my problem
Test.prototype.what = function() {
document.writeln("<br/>" + this.myArray);
}
Test.prototype.add = function() {
this.myArray.push(this.name);
}
var a = new Test('Scott');
a.add();
a.what();
var b = new Test('Smith');
document.writeln("<br/>" + b.myArray + " <= Check this one")
b.add()
b.what();
没有人触摸b对象数组,为什么javascript引擎从Class原型中获取它为什么不将它只取空数组属于该对象。
修改
所有答案都是正确的,让我们将属性类型更改为原始
function Test(name) {
this.name = name;
}
Test.prototype.primitive = 1;
Test.prototype.myArray = []; // I know if i move this to constructor it can resolve my problem
Test.prototype.what = function() {
document.writeln("<br/>" + this.myArray + " primitive:" +this.primitive);
}
Test.prototype.add = function() {
this.primitive++;
this.myArray.push(this.name);
}
var a = new Test('Scott');
a.add();
a.what();
var b = new Test('Smith');
document.writeln("<br/>" + b.myArray + " primitive:" +b.primitive +" <= Check this one now primtive is not shared")
b.add()
b.what();
因此,结论是附加到顶部原型的所有引用类型都共享给所有实例,而原始数据类型(如数字)则不是。
答案 0 :(得分:2)
没有人触摸b对象数组,为什么javascript引擎从Class原型中获取它为什么不采取空数组属于该对象
这就是原型在javascript中运行的方式。我们有object
,我们有prototype
。
这里的一个重要事实是,当您创建新对象时,它不会复制原型的所有属性和方法。
它实际上具有对prototype
对象的引用,并且属性/方法分辨率是动态执行的。
例如,如果您要求对象返回myArray
属性,则javascript会执行此操作:
object
有myArray
吗?不(因为你没有声明this.myArray)object.prototype
有myArray
吗?是object.prototype.myArray
现在,如果您创建两个Test
个对象,它们实际上具有相同的原型并引用相同的prototype.myArray
属性:
------------------
| Object a |
| | ---------------------
| name = 'Scott' | | |
| prototype ----|---------------> | prototype |
------------------ | |
| myArray = [] |
------------------ | |
| Object b | | |
| | | |
| name = 'Smith' | | |
| prototype ----|---------------> | |
------------------ ---------------------
由于a
和b
都具有相同的prototype
,因此它们也引用相同的myArray
。
这样,通过a
或b
对此数组进行修改会更改两个对象。
更新:如果prototype
具有原始值,则a
与b
之间仍会共享:
Test.prototype.primitive = 1
a = new Test();
a.primitive; // 1
b = new Test();
b.primitive; // 1
// Update prototype's primitive
Test.prototype.primitive += 1
// a and b objects refer to the updated value
a.primitive; // 2
b.primitive; // 2
但是当您执行a.primitive++
或更明确地a.primitive = a.primitive + 1
之类的操作时,您实际上会在primitive
对象中创建a
属性,但它不会引用prototype
了:
// Now a.primitive is actually created in the a object and
// does not refer to the prototype anymore
a.primitive++;
a.primitive; // 3
Test.prototype.primitive; // 2
b.prototype.primitive; // 2
// Now prototype primitive updates will only affect object b
Test.prototype.primitive += 2;
a.primitive; // 3
b.prototype.primitive; // 4
答案 1 :(得分:1)
为什么javascript引擎从Class原型中获取它为什么不将空数组属于该对象。
这就是典型的继承是如何运作的。由于您只为原型对象的属性分配了一个数组,而不是每个实例都有一个数组(就像在构造函数中创建赋值一样),只有不属于该对象的空数组并且属性查找转到原型。
答案 2 :(得分:0)
因为当您Test
执行测试时,您正在添加Test.prototype.myArray
。请将其保留在this.myArray
用
替换你的代码function Test(name) {
this.name = name; this.myArray = []; //observe this change
}
Test.prototype.what = function() {
console.log("<br/>" + this.myArray);
}
Test.prototype.add = function() {
this.myArray.push(this.name);
}
var a = new Test('Scott');
a.add();
a.what();
var b = new Test('Smith');
console.log("<br/>" + b.myArray + " <= Check this one")
b.add()
b.what();
答案 3 :(得分:0)
原型用作后备。 这意味着如果有问题的对象没有所请求的成员(方法或属性),则查询当前对象的原型以查找该成员。 如果不存在则会查询上层原型并且此过程一直持续到达 Object 原型,这是JavaScript中的基本原型。
以下是一个例子:
ICommand
到达对象原型时,如果仍未找到请求的成员,则会引发错误。
希望这一点。