我正在扩展像这样的对象:
Object.prototype.is_a = function (x) {
return this instanceof x;
}
一切按预期工作
"foo".is_a(String) // true
"foo".is_a(Object) // true
"foo".is_a(Array) // false
"foo".is_a(Function) // false
"foo".is_a(Boolean) // false
"foo".is_a(Date) // false
"foo".is_a(Number) // false
"foo".is_a(RegExp) // false
但是,
时"foo" instanceof String // false
this
功能上的 is_a()
关键字与foo
相同吗?为什么它会返回不同的结果?
答案 0 :(得分:10)
首先,您无法将instanceof
应用于原始值,这就是
"foo" instanceof String
返回false
。基元不是对象,因此不能是构造函数的实例。 *
那为什么它似乎在is_a
方法中有用?
在非严格模式下,函数is always going to be an object内的this
值(步骤3)。如果this
值不是对象,则将其隐式转换为1。您可以使用console.log(typeof this)
进行测试
这意味着字符串原语"foo"
将转换为String对象new String("foo")
,这就是您可以在其上使用instanceof
的原因。
在严格模式下,this
的值不必是对象,也不会自动转换(step 1)。在这种情况下,你的方法会失败:
> Object.prototype.is_a = function (x) {
'use strict';
return this instanceof x;
}
> "foo".is_a(String)
false
*:这是一个非常简化的解释。实际上,instanceof
运算符将评估委托给构造函数的内部[[HasInstance]]
method,如果传递的值不是对象,则将其定义为返回false
。
答案 1 :(得分:1)
字符串文字与String对象(MDN)不同。看起来字符串文字(字符串基元)在用作函数的绑定上下文时(即在函数内部this
时)会自动装入对象中:
>>> typeof "foo"
"string"
>>> Object.prototype.type_of = function (x) {
return typeof this;
}
function (x) {
return typeof this;
}
>>> "foo".type_of()
"object"
这也解释了你的行为实例。这表现得如你所料:
>>> new String("foo") instanceof String
true
>>> new String("foo") instanceof Object
true
>>> new String("foo").is_a(String)
true
>>> new String("foo").is_a(Object)
true
>>> new String("foo").is_a(Array)
false
答案 2 :(得分:1)
JavaScript包含字符串,数字和布尔值的原始版本和对象版本。字符串文字定义基元而不是对象。如果你做typeof "foo"
,你会得到“字符串”而不是“对象”。但是当你访问字符串的属性时,它会从原始字符串创建一个临时的String对象,然后访问该对象的相应属性,因此this instanceof String
在临时字符串中是真的对象的方法。
为了在考虑基元和对象的同时测试某些东西是否为字符串,您需要测试typeof foo === "string" || foo instanceof String
。
答案 3 :(得分:0)
instanceof需要定义一个对象,此示例返回true:
var f = new String("foo");
alert( f instanceof String);
这与您的示例更相似:
alert( new String("foo") instanceof String);