7

为什么以下两行返回不同的结果?

("test" instanceof String) // returns false
("test".constructor == String) // returns true

在 chrome 版本 28.0.1500.95 m 的控制台中测试

对于本机类型,它的工作方式是否略有不同?

4

2 回答 2

5

constructor只是内部[[prototype]]属性的一个属性,可以很容易地操纵:

function A(){}
function B(){}
A.prototype.constructor = B;

var a = new A();

console.log(a.constructor); //B

然而,instanceof操作员检查内部原型链并且不容易被愚弄,即使您更改prototype了构造函数的完整属性:

function A(){}
function B(){}
A.prototype = B.prototype;

var a = new A();

console.log(a instanceof A); //true
console.log(a instanceof B); //false

那么,为什么是"test" instanceof String === false但是("test".constructor == String) === true

首先,"test"是原语,原语永远不是任何事物的实例。使用时实际发生的是构造函数instanceof的内部[[HasInstance]]方法以可能的实例作为参数调用。所以a instanceof A大致翻译为:

`A.[[HasInstance]](a)`

ECMA 规范有这样的说法[[HasInstance]]: http: //www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.3

[[HasInstance]] (V)

假设 F 是一个 Function 对象。

当 F 的 [[HasInstance]] 内部方法以值 V 被调用时,采取以下步骤:

  1. 如果 V 不是对象,则返回 false。
  2. ……

换句话说:如果左侧instanceof不是对象,则运算符将返回false。

("test".constructor == String) === true出于不同的原因:如果您尝试访问原语的属性,该原语将临时转换为对象。所以"test".constructor大致等于:

(new String("test")).constructor

在这种情况下,您实际上是在使用构造函数创建一个对象,然后再请求该constructor属性。因此,它会返回也就不足为奇了String

于 2013-08-07T12:14:43.593 回答
1

主要区别在于instanceof检查对象的原型链,而检查构造函数只检查它是否是从同一个构造函数创建的。

例子:

function MyObject() {
    this.sayHi = function() { alert('Hi!'); }   
}

var x = new MyObject();
alert(x.constructor === Object);
alert(x instanceof Object);
于 2013-08-05T12:16:12.723 回答