instanceof
JavaScript 中的关键字在第一次遇到时可能会非常混乱,因为人们往往认为 JavaScript 不是面向对象的编程语言。
- 它是什么?
- 它解决了哪些问题?
- 什么时候合适,什么时候不合适?
instanceof
JavaScript 中的关键字在第一次遇到时可能会非常混乱,因为人们往往认为 JavaScript 不是面向对象的编程语言。
左侧 (LHS) 操作数是被测试到右侧 (RHS) 操作数的实际对象,右侧 (RHS) 操作数是类的实际构造函数。基本定义是:
Checks the current object and returns true if the object
is of the specified object type.
这里有一些很好的例子,这里有一个直接取自Mozilla 开发者网站的例子:
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral"; //no type specified
color2 instanceof String; // returns false (color2 is not a String object)
值得一提的是instanceof
,如果对象继承自类的原型,则评估结果为 true:
var p = new Person("Jon");
p instanceof Person
这是p instanceof Person
真的,因为p
继承自Person.prototype
.
当你声明一个变量时,你会给它一个特定的类型。
例如:
int i;
float f;
Customer c;
上面显示一些变量,即i
,f
和c
。类型是integer
,float
和用户定义的Customer
数据类型。上面的类型可以用于任何语言,而不仅仅是 JavaScript。但是,对于 JavaScript,当您声明一个变量时,您没有明确定义类型,var x
, x 可以是数字/字符串/用户定义的数据类型。那么instanceof
它的作用是检查对象以查看它是否属于指定的类型,因此从上面获取Customer
我们可以做的对象:
var c = new Customer();
c instanceof Customer; //Returns true as c is just a customer
c instanceof String; //Returns false as c is not a string, it's a customer silly!
上面我们已经看到,它c
是用类型声明的Customer
。我们已经对它进行了新的检查并检查了它是否属于类型Customer
。当然,它返回真。然后仍然使用该Customer
对象,我们检查它是否是String
. 不,绝对不是String
我们更新了一个Customer
对象而不是一个String
对象。在这种情况下,它返回 false。
真的就是这么简单!
到目前为止,任何评论中似乎都没有涵盖 instanceof 的一个重要方面:继承。由于原型继承,使用 instanceof 评估的变量可能为多个“类型”返回 true。
例如,让我们定义一个类型和一个子类型:
function Foo(){ //a Foo constructor
//assign some props
return this;
}
function SubFoo(){ //a SubFoo constructor
Foo.call( this ); //inherit static props
//assign some new props
return this;
}
SubFoo.prototype = Object.create(Foo.prototype); // Inherit prototype
SubFoo.prototype.constructor = SubFoo;
现在我们有几个“类”,让我们创建一些实例,并找出它们的实例:
var
foo = new Foo()
, subfoo = new SubFoo()
;
alert(
"Q: Is foo an instance of Foo? "
+ "A: " + ( foo instanceof Foo )
); // -> true
alert(
"Q: Is foo an instance of SubFoo? "
+ "A: " + ( foo instanceof SubFoo )
); // -> false
alert(
"Q: Is subfoo an instance of Foo? "
+ "A: " + ( subfoo instanceof Foo )
); // -> true
alert(
"Q: Is subfoo an instance of SubFoo? "
+ "A: " + ( subfoo instanceof SubFoo )
); // -> true
alert(
"Q: Is subfoo an instance of Object? "
+ "A: " + ( subfoo instanceof Object )
); // -> true
看到最后一行了吗?对函数的所有“新”调用都返回一个从 Object 继承的对象。即使在使用对象创建速记时也是如此:
alert(
"Q: Is {} an instance of Object? "
+ "A: " + ( {} instanceof Object )
); // -> true
那么“类”定义本身呢?它们是什么实例?
alert(
"Q: Is Foo an instance of Object? "
+ "A:" + ( Foo instanceof Object)
); // -> true
alert(
"Q: Is Foo an instance of Function? "
+ "A:" + ( Foo instanceof Function)
); // -> true
我觉得理解任何对象都可以是 MULTIPLE 类型的实例很重要,因为您(错误地)假设您可以通过使用instanceof
. 正如最后一个例子清楚地表明一个函数是一个对象。
如果您正在使用任何继承模式并希望通过鸭子类型以外的方法确认对象的后代,这也很重要。
希望可以帮助任何人探索instanceof
。
这里的其他答案是正确的,但它们没有instanceof
涉及实际工作原理,这可能是一些语言律师感兴趣的。
JavaScript 中的每个对象都有一个原型,可以通过__proto__
属性访问。函数也有一个prototype
属性,它是__proto__
由它们创建的任何对象的初始值。当一个函数被创建时,它被赋予一个唯一的对象prototype
。该instanceof
操作员使用这种独特性给你一个答案。以下是instanceof
可能的样子,如果你写一个函数。
function instance_of(V, F) {
var O = F.prototype;
V = V.__proto__;
while (true) {
if (V === null)
return false;
if (O === V)
return true;
V = V.__proto__;
}
}
这基本上是对 ECMA-262 5.1 版(也称为 ES5)第 15.3.5.3 节的解释。
请注意,您可以将任何对象重新分配给函数的prototype
属性,并且可以__proto__
在构造后重新分配对象的属性。这会给你一些有趣的结果:
function F() { }
function G() { }
var p = {};
F.prototype = p;
G.prototype = p;
var f = new F();
var g = new G();
f instanceof F; // returns true
f instanceof G; // returns true
g instanceof F; // returns true
g instanceof G; // returns true
F.prototype = {};
f instanceof F; // returns false
g.__proto__ = {};
g instanceof G; // returns false
我认为值得注意的是,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,而不使用它分配返回值。
您可以将其用于错误处理和调试,如下所示:
try{
somefunction();
}
catch(error){
if (error instanceof TypeError) {
// Handle type Error
} else if (error instanceof ReferenceError) {
// Handle ReferenceError
} else {
// Handle all other error types
}
}