This one just stabbed me hard. I don\'t know if it\'s the case with all browsers (I don\'t have any other competent browser to test with), but at least Firefox has two kind
Your comparing string values to string objects.
"a"
is a string value.
"a" === "a"; // true
new String("a")
is an string object.
new String("a") === new String("a"); // false
There both strings. "a"
just gets the string value "a" where as new String("a")
creates a new string object which internally has the string value "a"
There are two types of strings in Javascript -- literal strings and String objects. They do behave a little differently. The main difference between the two is that you can add additional methods and properties to a String object. For instance:
var strObj = new String("object mode");
strObj.string_mode = "object"
strObj.get_string_mode = function() { return this.string_mode; }
// this converts it from an Object to a primitive string:
str = strObj.toString();
A string literal is just temporarily cast to a String object to perform any of the core methods.
The same kinds of concepts apply to other data types, too. Here's more on primitive data types and objects.
EDIT
As noted in the comments, string literals are not primitive strings, rather a "literal constant whose type is a built-in primitive [string] value", citing this source.
Another important thing to remember is the following:
typeof "my-string" // "string"
typeof String('my-string') // 'string'
typeof new String("my-string") // "object".
Therefore, when testing whether an argument or variable is a string you need to do at least the following.
function isString(arg) {
if (!arg) {
return false;
}
return typeof arg == "string" || arg.constructor == String;
}
The above function will still fail if you pass in a String object from another frame/iframe. That is:
frames[0].myStringVar.constructor != frames[1].myStringVar.constructor
That is because the constructor String
is different for each window context. Therefore, a foolproof isString method would be
function isString(obj) {
return Object.prototype.toString.call(obj) == "[object String]";
}