是值是原始的还是盒装的

时间:2011-07-22 16:40:43

标签: javascript boxing typeof

可以使用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";
};

这两个函数是否有任何用例? (或NumberBoolean等的类似功能。

这个问题背后的概念来自以下Comment by T.J.Crowder

我们是否应该关心我们拥有的价值是原始的还是盒装的?

3 个答案:

答案 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 以及===通过引用对所有!==StringNumber进行了比较。

答案 2 :(得分:-2)

我使用underscore.js方法来检测变量的类型。尝试使用: isEmpty,isElement,isArray,isArguments,isFunction,isString,isNumber,isBoolean,isDate,isRegExp isNaN,isNull,isUndefined

这里描述: http://documentcloud.github.com/underscore/