admin管理员组

文章数量:1026989

The instanceof operator should look at the prototype, no? Why does it not change its answer after the object's prototype has been changed? Example below:

// The .prototype of objects created with 'new MyKlass'
// is MyKlass.prototype
var MyKlass = function(name, age) {
  this.name = name;
  this.age = age;
}

var xx = new MyKlass('xx', 20);
console.log(xx instanceof MyKlass);      // true, OK

xx.prototype = new String('s');
console.log(xx instanceof MyKlass);      // also true, WHY???

The instanceof operator should look at the prototype, no? Why does it not change its answer after the object's prototype has been changed? Example below:

// The .prototype of objects created with 'new MyKlass'
// is MyKlass.prototype
var MyKlass = function(name, age) {
  this.name = name;
  this.age = age;
}

var xx = new MyKlass('xx', 20);
console.log(xx instanceof MyKlass);      // true, OK

xx.prototype = new String('s');
console.log(xx instanceof MyKlass);      // also true, WHY???
Share Improve this question edited Jun 27, 2013 at 13:22 Denys Séguret 383k90 gold badges811 silver badges777 bronze badges asked Jun 27, 2013 at 13:01 zpzpzpzp 753 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 9

This case is explained in the MDN :

Note that if the value of an instanceof test can change based on changes to the prototype property of constructors, it cannot be changed by changing an object prototype, because changing an object prototype is not possible in standard ECMAScript. It is however possible using the non-standard __proto__ pseudo-property

This would log false :

xx.constructor.prototype = new String('s');
console.log(xx instanceof MyKlass);

In short, you shouldn't try to mutate JavaScript objects, they weren't designed to be mutable. I don't know what's your use case but there's probably a better solution, be it position, internal state, or something's else.

It does not look at .prototype but [[prototype]], or what is available in some browsers as .__proto__

xx.__proto__ = new String("s");
console.log(xx instanceof MyKlass); 
//false
console.log(xx instanceof String); 
//true

Assigning a .prototype property to a non function has no effect except the normal assignment of any normal property really. And for functions that only has an effect when the function is used in instanceof check or called with new.

The instanceof operator should look at the prototype, no?

Yes, it does. See the MDN docs.

Why does it not change its answer after the object's prototype has been changed?

var xx = new MyKlass('xx', 20);
xx.prototype = new String('s');

Because you didn't change the prototype of your xx object, but gave it a prototype property. Object.getPrototypeOf(xx) === MyKlass.prototype still applies. See __proto__ VS. prototype in JavaScript for details. What would work:

MyKlass.prototype = {}; // overwrite with a different object
console.log(xx instanceof MyKlass); // false now, xx doesn't inherit from the {}

or

xx.__proto__ = String.prototype; // or something
console.log(xx instanceof MyKlass); // false now, xx doesn't inherit from MyKlass.prototype

Notice that writing to the internal [[prototype]] via __proto__ is non-standard in ES5

The instanceof operator should look at the prototype, no? Why does it not change its answer after the object's prototype has been changed? Example below:

// The .prototype of objects created with 'new MyKlass'
// is MyKlass.prototype
var MyKlass = function(name, age) {
  this.name = name;
  this.age = age;
}

var xx = new MyKlass('xx', 20);
console.log(xx instanceof MyKlass);      // true, OK

xx.prototype = new String('s');
console.log(xx instanceof MyKlass);      // also true, WHY???

The instanceof operator should look at the prototype, no? Why does it not change its answer after the object's prototype has been changed? Example below:

// The .prototype of objects created with 'new MyKlass'
// is MyKlass.prototype
var MyKlass = function(name, age) {
  this.name = name;
  this.age = age;
}

var xx = new MyKlass('xx', 20);
console.log(xx instanceof MyKlass);      // true, OK

xx.prototype = new String('s');
console.log(xx instanceof MyKlass);      // also true, WHY???
Share Improve this question edited Jun 27, 2013 at 13:22 Denys Séguret 383k90 gold badges811 silver badges777 bronze badges asked Jun 27, 2013 at 13:01 zpzpzpzp 753 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 9

This case is explained in the MDN :

Note that if the value of an instanceof test can change based on changes to the prototype property of constructors, it cannot be changed by changing an object prototype, because changing an object prototype is not possible in standard ECMAScript. It is however possible using the non-standard __proto__ pseudo-property

This would log false :

xx.constructor.prototype = new String('s');
console.log(xx instanceof MyKlass);

In short, you shouldn't try to mutate JavaScript objects, they weren't designed to be mutable. I don't know what's your use case but there's probably a better solution, be it position, internal state, or something's else.

It does not look at .prototype but [[prototype]], or what is available in some browsers as .__proto__

xx.__proto__ = new String("s");
console.log(xx instanceof MyKlass); 
//false
console.log(xx instanceof String); 
//true

Assigning a .prototype property to a non function has no effect except the normal assignment of any normal property really. And for functions that only has an effect when the function is used in instanceof check or called with new.

The instanceof operator should look at the prototype, no?

Yes, it does. See the MDN docs.

Why does it not change its answer after the object's prototype has been changed?

var xx = new MyKlass('xx', 20);
xx.prototype = new String('s');

Because you didn't change the prototype of your xx object, but gave it a prototype property. Object.getPrototypeOf(xx) === MyKlass.prototype still applies. See __proto__ VS. prototype in JavaScript for details. What would work:

MyKlass.prototype = {}; // overwrite with a different object
console.log(xx instanceof MyKlass); // false now, xx doesn't inherit from the {}

or

xx.__proto__ = String.prototype; // or something
console.log(xx instanceof MyKlass); // false now, xx doesn't inherit from MyKlass.prototype

Notice that writing to the internal [[prototype]] via __proto__ is non-standard in ES5

本文标签: javascriptwhy instanceof keeps saying true after prototype changedStack Overflow