Имеет ли значение, является ли значение примитивным или в штучной упаковке
Можно использовать 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
, так далее).
Концепция этого вопроса возникла из следующего комментария TJCrowder.
Должны ли мы когда-либо интересоваться, является ли ценность, которую мы имеем, примитивной или коробочной?
3 ответа
Я бы сказал, что в этом нет никакого смысла, вам почти все равно, имеете ли вы дело с 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);
... затем свойство добавляется к этому объекту, и вызывающий код может видеть его. Рассмотрим ( живая копия):
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";
}
Выход:
[До] typeof s1.foo = не определено [После] typeof s1.foo = не определено [До] typeof s2.foo = не определено [После] typeof s2.foo = строка
Обратите внимание, что s2.foo
это строка, но s1.foo
нет (потому что s1
был строковым примитивом, объект, созданный, когда мы продвигали его в test
не имеет ничего общего с вызывающим кодом).
Есть ли вариант использования для этого? Не знаю. Я бы сказал, что это будет чрезвычайно острый случай.
Все toString
Кажется, что это попытка обойти проблемы с кросс-кадровым микшированием String
Конструкторы. Это не нужно для проверки, является ли что-то примитивной строкой - typeof
достаточно, поэтому нет никакого варианта использования для is_primitive_string
,
Я очень редко вижу аргументы в качестве String
случаи, поэтому я не могу понять, почему мне нужно проверить, является ли что-то String
Экземпляр кросс-кадр вместо просто принуждения к String
значение через ("" + s)
или же String(s)
, Единственный раз, когда я использовал 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";
добавляется в начало Boolean.prototype.not
в действительном переводчике ES5.
С Number
s, сравнения с использованием <
все в порядке и сложение, а другие операторы, как правило, работают как положено new Number(0)
а также new Number(NaN)
есть те же проблемы, что и new Boolean(false)
вокруг условий, и, конечно,
alert(NaN === NaN); // false
var NAN = new Number(NaN);
alert(NAN === NAN); // true
а также ===
а также !==
сравнить по ссылке для всех String
, Number
, а также Boolean
,
Я использую методы underscore.js, чтобы определить тип переменной. Попробуйте использовать: isEmpty, isElement, isArray, isArguments, isFunction, isString, isNumber, isBoolean, isDate, isRegExp isNaN, isNull, isUndefined
Описано здесь: http://documentcloud.github.com/underscore/