Problem extending class with javascript object pro

2019-04-29 09:53发布

I have got this problem... B is a base class, and A is a derived class... Event though A is derived from B, various objects of A points to the same object of B.

I know i have assigned an object of B to the prototype of A to make A child of B.

But different objects of A, they should have different address space to hold the variables, right? Can you anyone correct this?

    function B(){

        this.obj = {};
    }

    function A(){

    }

    A.prototype = new B();

    var a = new A();
    var b = new A();
    var c = new A();

    console.log(a.obj == b.obj); //prints true
    console.log(a.obj === b.obj); //prints true

    a.obj.name = "stackoverflow";
    console.log(b.obj.name); //prints stackoverflow

What change should I make in this code so that gives me following result.

a.obj === b.obj  //must be false

a instanceof A;  //must be true
a instanceof B;  //must be true

4条回答
女痞
2楼-- · 2019-04-29 10:30

Values are assigned by reference, and since all instances of A use the same instance of B as their prototype, they all refer to the same 'B'.

So this is exactly what's expected here. One way to solve this, is to add (for instance) a 'initialize' method the B 'class', which you could then call from within the A constructor.

You can also not use 'new B()' to define the prototype, and use Object.create instead. Object.create does not call B's constructor, but you can then call the parent constructor from A.

function A() {
   B.call(this);
}
查看更多
仙女界的扛把子
3楼-- · 2019-04-29 10:43

That's why you shouldn't have mutable values (particularly objects or arrays) on a prototype - the same value will be shared across all object instances and can be changed in any of them. Here you can avoid the problem by using Object.create that won't call the constructor of B when creating the prototype:

A.prototype = Object.create(B.prototype);

Constructor of A should then call the constructor of B for each new object:

function A() {
  B.call(this);
}

For browsers that don't support Object.create() you can emulate it as mentioned on http://javascript.crockford.com/prototypal.html.

查看更多
贼婆χ
4楼-- · 2019-04-29 10:43

If you want instances of A to have a local property obj, add the property to A, not to B

function B(){
}

function A(){
  this.obj = {};  // <<< this.obj here
}

A.prototype = new B();

var a = new A();
var b = new A();
var c = new A();

console.log(a.obj == b.obj); //=> prints false
console.log(a.obj === b.obj); //=> prints false

a.obj.name = "stackoverflow";
console.log(b.obj.name); //=> undefined

another way to have a local obj property for instances of A is to use a setter method in B's prototype:

function B(){
   B.prototype.setObj = function(obj){
     this.obj = obj;
     return this;
   }
 }
 //...
 a.setObj({}).name = "stackoverflow";
 console.log(a.obj.name); //=>prints stackoverflow
 console.log(b.obj.name); //=>undefined
查看更多
Juvenile、少年°
5楼-- · 2019-04-29 10:49

This is a part of prototypes in Javascript, I suggest you read this excellent thread.

查看更多
登录 后发表回答