第一次遇到JavaScript中的instanceof关键字时,可能会让人非常困惑,因为人们倾向于认为JavaScript不是面向对象的编程语言。
是什么? 它能解决什么问题? 什么时候合适,什么时候不合适?
第一次遇到JavaScript中的instanceof关键字时,可能会让人非常困惑,因为人们倾向于认为JavaScript不是面向对象的编程语言。
是什么? 它能解决什么问题? 什么时候合适,什么时候不合适?
当前回答
@SebastianSimon我最后的答案是8岁(那时我跛了),有可能我写了一些牛逼的东西:)
简单地说——目前我使用instanceof的唯一情况是当我使用类实例时,行为取决于我将接收的类,例如。我想区分404是否为ErrorA(资源不存在)或ErrorB(服务未找到)-库响应代码令人困惑,但我的运气是使用不同的错误类抛出。
当然(目前)我不会用它来检查反映原语的类型——你不能确定库是否返回'msg'或new String('msg')。
它们都有属于String类的方法,因为'msg'原语在内部包装成字符串对象。内部是指通过解释器。它们都是字符串,但instanceof操作符似乎在这里是不够的-检查某事物是否是原始或类,我会使用typeof && instanceof的混合-但仅用于从外部JS库返回的东西。
目前TypeScript正在解决这个问题,你不再需要使用typeof和instanceof这样繁琐的检查。
其他回答
我认为值得注意的是,instanceof是在声明对象时使用“new”关键字定义的。在JonH的例子中;
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)
他没有提到的是;
var color1 = String("green");
color1 instanceof String; // returns false
指定"new"实际上是将String构造函数的结束状态复制到color1变量中,而不仅仅是将其设置为返回值。我认为这更好地展示了new关键字的功能;
function Test(name){
this.test = function(){
return 'This will only work through the "new" keyword.';
}
return name;
}
var test = new Test('test');
test.test(); // returns 'This will only work through the "new" keyword.'
test // returns the instance object of the Test() function.
var test = Test('test');
test.test(); // throws TypeError: Object #<Test> has no method 'test'
test // returns 'test'
使用"new"将函数内的"this"值赋给已声明的var,而不使用它则赋给返回值。
instanceof只是isPrototypeOf的语法糖:
function Ctor() {}
var o = new Ctor();
o instanceof Ctor; // true
Ctor.prototype.isPrototypeOf(o); // true
o instanceof Ctor === Ctor.prototype.isPrototypeOf(o); // equivalent
Instanceof仅仅依赖于对象构造函数的原型。
构造函数只是一个普通的函数。严格来说,它是一个函数对象,因为在Javascript中所有东西都是对象。这个函数对象有一个原型,因为每个函数都有一个原型。
原型只是一个普通的对象,它位于另一个对象的原型链中。这意味着在另一个对象的原型链中使一个对象成为原型:
function f() {} // ordinary function
var o = {}, // ordinary object
p;
f.prototype = o; // oops, o is a prototype now
p = new f(); // oops, f is a constructor now
o.isPrototypeOf(p); // true
p instanceof f; // true
应该避免使用instanceof操作符,因为它伪造了Javascript中不存在的类。尽管class关键字在ES2015中也没有,因为class只是语法糖…但那是另一个故事了。
是什么?
Javascript是一种原型语言,这意味着它使用原型进行“继承”。instanceof操作符测试构造函数的prototype属性类型是否存在于对象的__proto__链中。这意味着它将执行以下操作(假设testObj是一个函数对象):
obj instanceof testObj;
Check if prototype of the object is equal to the prototype of the constructor: obj.__proto__ === testObj.prototype >> if this is true instanceof will return true. Will climb up the prototype chain. For example: obj.__proto__.__proto__ === testObj.prototype >> if this is true instanceof will return true. Will repeat step 2 until the full prototype of object is inspected. If nowhere on the prototype chain of the object is matched with testObj.prototype then instanceof operator will return false.
例子:
人(名){ This.name = name; } var me =新人(“威廉”); console.log(me instanceof Person);/ /正确的 //因为:我。__proto__ === Person。Prototype //计算结果为true console.log(me instanceof Object);/ /正确的 // because: me.__proto__。__proto__ ===对象。Prototype //计算结果为true console.log(me instanceof Array);/ /错误 数组不在原型链上
它能解决什么问题?
它解决了方便地检查对象是否来自某个原型的问题。例如,当一个函数接收到一个可以有各种原型的对象时。然后,在使用原型链中的方法之前,我们可以使用instanceof操作符来检查这些方法是否在对象上。
例子:
function Person1 (name) { this.name = name; } function Person2 (name) { this.name = name; } Person1.prototype.talkP1 = function () { console.log('Person 1 talking'); } Person2.prototype.talkP2 = function () { console.log('Person 2 talking'); } function talk (person) { if (person instanceof Person1) { person.talkP1(); } if (person instanceof Person2) { person.talkP2(); } } const pers1 = new Person1 ('p1'); const pers2 = new Person2 ('p2'); talk(pers1); talk(pers2);
在talk()函数中,首先检查原型是否位于对象上。在此之后,选择适当的方法来执行。不进行此检查可能导致执行一个不存在的方法,从而导致引用错误。
什么时候合适,什么时候不合适?
我们已经讲过了。当您需要在对对象进行操作之前检查对象的原型时,可以使用它。
//Vehicle is a function. But by naming conventions
//(first letter is uppercase), it is also an object
//constructor function ("class").
function Vehicle(numWheels) {
this.numWheels = numWheels;
}
//We can create new instances and check their types.
myRoadster = new Vehicle(4);
alert(myRoadster instanceof Vehicle);
你可以用它来进行错误处理和调试,就像这样:
try{
somefunction();
}
catch(error){
if (error instanceof TypeError) {
// Handle type Error
} else if (error instanceof ReferenceError) {
// Handle ReferenceError
} else {
// Handle all other error types
}
}