可以使用typeof
来确定值是原始值还是已装箱。
考虑:
typeof "foo"; // "string"
typeof new String("foo"); // "object"
结合Object.prototype.toString
,我们可以定义以下两个函数
var toString = Object.prototype.toString;
var is_primitive_string = function(s) {
return toString.call(s) === "[object String]" && typeof s === "string";
};
var is_boxed_string = function(s) {
return toString.call(s) === "[object String]" && typeof s === "object";
};
这两个函数是否有任何用例? (或Number
,Boolean
等的类似功能。
这个问题背后的概念来自以下Comment by T.J.Crowder。
我们是否应该关心我们拥有的价值是原始的还是盒装的?
答案 0 :(得分:7)
我说几乎没有意义,你几乎不关心你是在处理string
原语还是String
对象。
有边缘情况。例如,String
对象是实际对象,您可以向其添加属性。这可以让你做到这样的事情:
function test(arg) {
arg.foo = "bar";
}
如果调用代码传入string
原语:
var s1 = "str";
test(s1);
... arg
被提升为String
对象并添加了一个属性,但String
之后的任何内容都没有使用test
对象
相反,如果调用代码传入String
对象:
var s2 = new String("str");
test(s2);
...然后将属性添加到该对象,调用代码可以看到它。考虑(live copy):
var s1, s2;
s1 = "str";
display("[Before] typeof s1.foo = " + typeof s1.foo);
test(s1);
display("[After] typeof s1.foo = " + typeof s1.foo);
s2 = new String("str");
display("[Before] typeof s2.foo = " + typeof s2.foo);
test(s2);
display("[After] typeof s2.foo = " + typeof s2.foo);
function test(arg) {
arg.foo = "bar";
}
输出:
[Before] typeof s1.foo = undefined [After] typeof s1.foo = undefined [Before] typeof s2.foo = undefined [After] typeof s2.foo = string
请注意,s2.foo
是一个字符串,但s1.foo
不是(因为s1
是一个字符串 primitive ,当我们在其中提升它时创建的对象test
与调用代码无关。)
这有什么用例吗?不知道。如果是这样的话,我会说这将是一个非常尖锐的边缘案例。
答案 1 :(得分:3)
所有toString
内容似乎都是尝试解决不同内置String
构造函数的跨框架混合问题。这对于检查某些内容是否是原始字符串是不必要的 - typeof
就足够了,因此is_primitive_string
没有用例。
我很少看到作为String
实例传递的参数,所以我无法理解为什么我需要检查某些内容是否是String
实例跨框架而不是仅仅强制转换为{{1通过String
或("" + s)
的值。我在生产代码中使用String(s)
值的唯一一次是当我需要一个空字符串时,在某些highly optimized code中是真实的。
就其他人而言,String
类的实例表现不像人们在条件中所期望的那样。
Boolean
if (new Boolean(false)) {
alert("WTF!");
} else {
alert("OK");
}
Boolean.prototype.not = function () { return !this; };
if (new Boolean(false).not()) {
alert("OK");
} else {
alert("Really, WTF!");
}
if (false.not()) { // Autoboxing
alert("OK");
} else {
alert("Cmon, WTF!");
}
是!(false)
,但是当您使用创建true
类的实例时,Boolean
运算符应用于对象值,并且对象值始终是真实的
我相信EcmaScript 5严格模式正在改变!
呈现的方式,因此最后一个示例(this
)的行为与false.not()
添加到顶部时可能会天真地期望的一样"use strict";
在有效的ES5口译员中。
使用Boolean.prototype.not
s,使用Number
进行比较是正常的,并且添加和其他运算符倾向于按预期工作。 <
和new Number(0)
与条件相同的问题new Number(NaN)
,当然还有
new Boolean(false)
和alert(NaN === NaN); // false
var NAN = new Number(NaN);
alert(NAN === NAN); // true
以及===
通过引用对所有!==
,String
和Number
进行了比较。
答案 2 :(得分:-2)
我使用underscore.js方法来检测变量的类型。尝试使用: isEmpty,isElement,isArray,isArguments,isFunction,isString,isNumber,isBoolean,isDate,isRegExp isNaN,isNull,isUndefined