Имеет ли значение, является ли значение примитивным или в штучной упаковке

Можно использовать 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.

С Numbers, сравнения с использованием < все в порядке и сложение, а другие операторы, как правило, работают как положено 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/

Другие вопросы по тегам