简体   繁体   English

Javascript函数的原型在对象之间共享?

[英]Javascript functions' prototype is shared between objects??

All the resources I have found, it says that if we use Javascript prototype pattern, that functions' prototype is shared between all the objects for that particular type. 我找到的所有资源都表示,如果我们使用Javascript原型模式,那么函数'prototype'将在该特定类型的所有对象之间共享。 that means the following; 这意味着以下;

function TestObj(){
}

TestObj.prototype = {
    cVar: 15,
    increase: function(){
        this.cVar++;
    }
};

var a = new TestObj();
var b = new TestObj();
a.increase();
console.log(a.cVar); // 16
console.log(b.cVar); // 15 ??

Now my question is, shouldn't the b.cVar be 16? 现在我的问题是,b.cVar不应该是16吗? why is it 15 then? 那为什么呢? And if it is 15 that means the TestObj with protype is not shared between objects. 如果它是15则意味着具有protype的TestObj不在对象之间共享。

Do you know?? 你知道吗??

Yes, an object's prototype is shared between instances of the object, but the this.cVar++ looks a little bit misleading. 是的,对象的原型在对象的实例之间共享,但this.cVar++看起来有点误导。

I think its easier to explain if you rewrite 如果你重写,我认为更容易解释

this.cVar++;

as

this.cVar = this.cVar + 1;

The important thing is that this refers to the object instance and not the prototype. 重要的是, this是指对象实例,而不是原型。 So in this.cVar + 1 it'll check the object instance to see if it has a cVar property. 因此,在this.cVar + 1它将检查对象实例以查看它是否具有cVar属性。 The first time increase is called, it doesn't. 第一次调用increase ,但事实并非如此。 So JavaScript will look up the prototype chain until it finds it. 所以JavaScript会查找原型链,直到找到它为止。 So it finds 15 . 所以它找到15 However, when it does the actual assignment back to this.cVar , it sets the property on the object instance itself and not the prototype (a shadowing of sorts). 但是,当它实际返回this.cVar ,它会在对象实例本身上设置属性,而不是原型( this.cVar的阴影)。

So in your example, 所以在你的例子中,

console.log(a.cVar); // returns property from `a` itself
console.log(b.cVar); // returns property from the prototype

We can show this by using hasOwnProperty : 我们可以使用hasOwnProperty来显示:

console.log( a.hasOwnProperty( "cVar" ) ); // true
console.log( b.hasOwnProperty( "cVar" ) ); // false

Objects do, in fact, share the prototype with one another as your research has lead you to believe. 事实上,物体确实彼此共享原型,因为您的研究已经让您相信。 However, as go-oleg eluded to, there is a concept of the prototype chain. 然而,正如go-oleg所说,有一个原型链的概念。 The prototype chain has a couple of behaviors you have to understand. 原型链有一些您必须了解的行为。

When you try to access a property on an object, it recursively looks up the chain starting from the object and looks for the property, then returns the value ( This is what happens in the case of a read/get action ). 当您尝试访问对象上的属性时,它以递归方式从对象开始查找链并查找该属性,然后返回该值( 这是在读取/获取操作的情况下发生的情况 )。

When you try to set the value on a property on an object, it doesn't bother to recurse up the chain to find the property in the chain. 当您尝试在对象上的属性上设置值时,它不会在链中递归以查找链中的属性。 Instead, if it doesn't find one on the object, it just adds the property along with the value you set on the object itself. 相反,如果它没有在对象上找到一个,它只会添加属性以及您在对象本身上设置的值。 This effectively hides the property that is higher up the prototype chain ( This is what happens in the case of a write/set action ). 这有效地隐藏了原型链中较高的属性( 这是在写入/设置操作的情况下发生的情况 )。

If you placed your value inside an object then tried to set the value however, it would recurse to the object reference in a read attempt and since you have a reference pointer to the object, you would be setting the value on the object directly which would have the outcome you were expecting: 如果您将值放在一个对象中然后尝试设置该值,它会在读取尝试时递归到对象引用,并且由于您有一个指向该对象的引用指针,您将直接在该对象上设置该值,得到你期待的结果:

function TestObj(){
}

TestObj.prototype = {
    cVar: 15,
    obj: { val: 5 },
    increase: function(){
        this.cVar++;
    },
    objInc: function() { 
        this.obj.val++;
    }
};

var a = new TestObj();
var b = new TestObj();
a.increase();
console.log(a.cVar);
console.log(b.cVar);

b.objInc();
console.log(a.obj.val);
console.log(b.obj.val);

//output
//16
//15
//6
//6

Hopefully that distinction clears up the confusion. 希望这种区别可以消除混乱。

To be clear, "a" is an object, "b" is another, separate, object. 要清楚,“a”是一个对象,“b”是另一个独立的对象。 You then call the increase function only on "a", not "b". 然后,您只能在“a”而不是“b”上调用增量功能。 Therefore, unless I'm off my rocker, It would make sense that b.cVar = 15, since it was never incremented. 因此,除非我离开摇杆,否则b.cVar = 15是有意义的,因为它从未增加。

Your getting confused by the terminology, and TestObject a is the only TestObject that you call increase() on. 您对术语感到困惑,而TestObject a是您调用increase()的唯一TestObject So it makes sense that a = 16 and b = 16 , since you never call b.increase() . 所以a = 16b = 16是有意义的,因为你从不调用b.increase()

... that functions' prototype is shared between all the objects for that particular type. ...函数的原型在该特定类型的所有对象之间共享。

That doesn't mean that each time any TestObject calls increase() then every other TestObject and itself also increase their cVar . 这并不意味着每次TestObject调用increase()每个其他TestObject本身也会增加它们的cVar Your thinking of something similar to the way that an EventListener and EventDispatcher system is set up. 您对类似于设置EventListenerEventDispatcher系统的方式的想法。 That function's prototype shared between all the objects for that particular type means that each TestObject instance has the prototype you defined. 该函数的原型在该特定类型的所有对象之间共享意味着每个TestObject实例都具有您定义的原型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM