Why are my JavaScript object properties being over

2020-01-25 10:04发布

问题:

I created an object like the following.

var BaseObject = function(){

var base = this;
base.prop;

base.setProp = function(val){
    base.prop = val;
}
}

When I call the setProp method, I get the following.

var a = new BaseObject();
var b = new BaseObject();           

a.setProp("foo");
b.setProp("bar");

console.log(a.prop); // outputs 'foo'
console.log(b.prop); // outputs 'bar'

I then created another object that inherits from BaseObject like this.

var TestObject = function(){
    // do something
}

TestObject.prototype = new BaseObject();

When I do the same, I get a result I wasn't expecting.

var a = new TestObject();
var b = new TestObject();

a.setProp("foo");
b.setProp("bar");

console.log(a.prop); // outputs 'bar'
console.log(b.prop); // outputs 'bar'

I don't know why. I've been reading alot about closures and prototypal inheritance recently and I suspect I've gotten it all confused. So any pointers on why this particular example works the way it does would be greatly appreciated.

回答1:

There is only one BaseObject instance from which all TestObjects inherit. Don't use instances for creating prototype chains!

What you want is:

var TestObject = function(){
    BaseObject.call(this); // give this instance own properties from BaseObject
    // do something
}
TestObject.prototype = Object.create(BaseObject.prototype);

See JavaScript inheritance: Object.create vs new, Correct javascript inheritance and What is the reason to use the 'new' keyword at Derived.prototype = new Base for a detailed explanation of the problems with new. Also have a look at Crockford's Prototypal inheritance - Issues with nested objects



回答2:

Think of protoypal inheritance as dealing solely with objects and without the concept of classes. In your code you have a BaseObject object which has a prop attribute. You have 2 other objects that extend from 1 instance of that object, but the property belongs to the original object. If you need each object to have their own copy, then they need to be given a distinct variable that is intialized for that object (such as in their constructor).

As an aside the Java style accessors are overkill in JavaScript (you can intercept access natively if needed) and can further muddy these questions since they will behave differently.