使用instanceof和检查构造函数之间有什么区别?

时间:2013-08-05 10:29:44

标签: javascript

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

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

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

对于原生类型,它的工作方式会有所不同吗?

2 个答案:

答案 0 :(得分: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对象。

     

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

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

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

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

(new String("test")).constructor

在这种情况下,您实际上是使用构造函数创建一个对象,然后请求constructor属性。因此毫不奇怪,它将返回String

答案 1 :(得分:1)

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

示例:

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

var x = new MyObject();
alert(x.constructor === Object);
alert(x instanceof Object);