Just curious:
4 instanceof Number => false
new Number(4) instanceof Number => true?
Why is this? Same with strings:
'some string' instanceof String returns false
new String('some string') instanceof String => true
String('some string') instanceof String also returns false
('some string').toString instanceof String also returns false
For object, array or function types the instanceof operator works as expected. I just don't know how to understand this.
[new insights]
Object.prototype.is = function() {
var test = arguments.length ? [].slice.call(arguments) : null
,self = this.constructor;
return test ? !!(test.filter(function(a){return a === self}).length)
: (this.constructor.name ||
(String(self).match ( /^function\s*([^\s(]+)/im )
|| [0,'ANONYMOUS_CONSTRUCTOR']) [1] );
}
// usage
var Newclass = function(){}; // anonymous Constructor function
var Some = function Some(){}; // named Constructor function
(5).is(); //=> Number
'hello world'.is(); //=> String
(new Newclass()).is(); //=> ANONYMOUS_CONSTRUCTOR
(new Some()).is(); //=> Some
/[a-z]/.is(); //=> RegExp
'5'.is(Number); //=> false
'5'.is(String); //=> true
value instanceof Constructor is the same as Constructor.prototype.isPrototypeOf(value) and both check the [[Prototype]]-chain of value for occurences of a specific object.
Strings and numbers are primitive values, not objects and therefore don't have a [[Prototype]], so it'll only work if you wrap them in regular objects (called 'boxing' in Java).
Also, as you noticed, String(value) and new String(value) do different things: If you call the constructor functions of the built-in types without using the new operator, they try to convert ('cast') the argument to the specific type. If you use the new operator, they create a wrapper object.
new String(value) is roughly equivalent to Object(String(value)), which behaves the same way as new Object(String(value)).
Some more on types in JavaScript: ECMA-262 defines the following primitive types: Undefined, Null, Boolean, Number, and String. Additionally, there is the type Object for things which have properties.
For example, functions are of type Object (they just have a special property called [[Call]]), and null is a primitive value of type Null. This means that the result of the typeof operator doesn't really return the type of a value...
Aditionally, JavaScript objects have another property called [[Class]]. You can get it via Object.prototype.toString.call(value) (this will return '[objectClassname]'). Arrays and functions are of the type Object, but their classes are Array and Function.
The test for an object's class given above works when instanceof fails (e.g. when objects are passed between window/frame boundaries and don't share the same prototypes).
Also, you might want to check out this improved version of typeof:
function typeOf(value) {
var type = typeof value;
switch(type) {
case 'object':
return value === null ? 'null' : Object.prototype.toString.call(value).
match(/^\[object (.*)\]$/)[1]
case 'function':
return 'Function';
default:
return type;
}
}
For primitives, it will return their type in lower case, for objects, it will return their class in title case.
Examples:
For primitives of type Number (eg 5), it will return 'number', for wrapper objects of class Number (eg new Number(5)), it will return 'Number';
For functions, it will return 'Function'.
If you don't want to discern between primitive values and wrapper objects (for whatever, probably bad reason), use typeOf(...).toLowerCase().
Known bugs are some built-in functions in IE, which are considered 'Object' and a return value of 'unknown' when used with some COM+ objects.
You may try to evaluate:
>>> typeof("a")
"string"
>>> typeof(new String("a"))
"object"
>>> typeof(4)
"number"
>>> typeof(new Number(4))
"object"
As stated in Christoph's answer, string and number literals are not the same as String and Number objects. If you use any of the String or Number methods on the literal, say
'a string literal'.length
The literal is temporarily converted to an object, the method is invoked and the object is discarded.
Literals have some distinct advantages over objects.
//false, two different objects with the same value
alert( new String('string') == new String('string') );
//true, identical literals
alert( 'string' == 'string' );
Always use literals to avoid unexpected behaviour!
You can use Number() and String() to typecast if you need to:
//true
alert( Number('5') === 5 )
//false
alert( '5' === 5 )
In the case of primitive numbers, the isNaN method could also help you.
This is a nuance of Javascript which I've found catches some out. The instanceof of operator will always result in false if the LHS is not an object type.
Note that new String('Hello World') does not result in a string type but is an object. The new operator always results in an object. I see this sort of thing:
function fnX(value)
{
if (typeof value == 'string')
{
//Do stuff
}
}
fnX(new String('Hello World'));
The expectation is that "Do Stuff" will happen but it doesn't because the typeof the value is object.
Related
"foo" instanceof String //=> false
"foo" instanceof Object //=> false
true instanceof Boolean //=> false
true instanceof Object //=> false
false instanceof Boolean //=> false
false instanceof Object //=> false
12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true
// the tests against Object really don't make sense
Array literals and Object literals match...
[0,1] instanceof Array //=> true
{0:1} instanceof Object //=> true
Why don't all of them? Or, why don't they all not?
And, what are they an instance of, then?
It's the same in FF3, IE7, Opera, and Chrome. So, at least it's consistent.
Primitives are a different kind of type than objects created from within Javascript. From the Mozilla API docs:
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)
I can't find any way to construct primitive types with code, perhaps it's not possible. This is probably why people use typeof "foo" === "string" instead of instanceof.
An easy way to remember things like this is asking yourself "I wonder what would be sane and easy to learn"? Whatever the answer is, Javascript does the other thing.
I use:
function isString(s) {
return typeof(s) === 'string' || s instanceof String;
}
Because in JavaScript strings can be literals or objects.
In JavaScript everything is an object (or may at least be treated as an object), except primitives (booleans, null, numbers, strings and the value undefined (and symbol in ES6)):
console.log(typeof true); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof function () {}); // function
As you can see objects, arrays and the value null are all considered objects (null is a reference to an object which doesn't exist). Functions are distinguished because they are a special type of callable objects. However they are still objects.
On the other hand the literals true, 0, "" and undefined are not objects. They are primitive values in JavaScript. However booleans, numbers and strings also have constructors Boolean, Number and String respectively which wrap their respective primitives to provide added functionality:
console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0)); // object
console.log(typeof new String("")); // object
As you can see when primitive values are wrapped within the Boolean, Number and String constructors respectively they become objects. The instanceof operator only works for objects (which is why it returns false for primitive values):
console.log(true instanceof Boolean); // false
console.log(0 instanceof Number); // false
console.log("" instanceof String); // false
console.log(new Boolean(true) instanceof Boolean); // true
console.log(new Number(0) instanceof Number); // true
console.log(new String("") instanceof String); // true
As you can see both typeof and instanceof are insufficient to test whether a value is a boolean, a number or a string - typeof only works for primitive booleans, numbers and strings; and instanceof doesn't work for primitive booleans, numbers and strings.
Fortunately there's a simple solution to this problem. The default implementation of toString (i.e. as it's natively defined on Object.prototype.toString) returns the internal [[Class]] property of both primitive values and objects:
function classOf(value) {
return Object.prototype.toString.call(value);
}
console.log(classOf(true)); // [object Boolean]
console.log(classOf(0)); // [object Number]
console.log(classOf("")); // [object String]
console.log(classOf(new Boolean(true))); // [object Boolean]
console.log(classOf(new Number(0))); // [object Number]
console.log(classOf(new String(""))); // [object String]
The internal [[Class]] property of a value is much more useful than the typeof the value. We can use Object.prototype.toString to create our own (more useful) version of the typeof operator as follows:
function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
console.log(typeOf(true)); // Boolean
console.log(typeOf(0)); // Number
console.log(typeOf("")); // String
console.log(typeOf(new Boolean(true))); // Boolean
console.log(typeOf(new Number(0))); // Number
console.log(typeOf(new String(""))); // String
Hope this article helped. To know more about the differences between primitives and wrapped objects read the following blog post: The Secret Life of JavaScript Primitives
You can use constructor property:
'foo'.constructor == String // returns true
true.constructor == Boolean // returns true
typeof(text) === 'string' || text instanceof String;
you can use this, it will work for both case as
var text="foo"; // typeof will work
String text= new String("foo"); // instanceof will work
This is defined in the ECMAScript specification Section 7.3.19 Step 3: If Type(O) is not Object, return false.
In other word, if the Obj in Obj instanceof Callable is not an object, the instanceof will short-circuit to false directly.
I believe I have come up with a viable solution:
Object.getPrototypeOf('test') === String.prototype //true
Object.getPrototypeOf(1) === String.prototype //false
The primitive wrapper types are reference types that are automatically created behind the scenes whenever strings, numbers, or Booleans
are read.For example :
var name = "foo";
var firstChar = name.charAt(0);
console.log(firstChar);
This is what happens behind the scenes:
// what the JavaScript engine does
var name = "foo";
var temp = new String(name);
var firstChar = temp.charAt(0);
temp = null;
console.log(firstChar);
Because the second line uses a string (a primitive) like an object,
the JavaScript engine creates an instance of String so that charAt(0) will
work.The String object exists only for one statement before it’s destroyed
check this
The instanceof operator returns false because a temporary object is
created only when a value is read. Because instanceof doesn’t actually read
anything, no temporary objects are created, and it tells us the values aren’t
instances of primitive wrapper types. You can create primitive wrapper
types manually
For me the confusion caused by
"str".__proto__ // #1
=> String
So "str" istanceof String should return true because how istanceof works as below:
"str".__proto__ == String.prototype // #2
=> true
Results of expression #1 and #2 conflict each other, so there should be one of them wrong.
#1 is wrong
I figure out that it caused by the __proto__ is non standard property, so use the standard one:Object.getPrototypeOf
Object.getPrototypeOf("str") // #3
=> TypeError: Object.getPrototypeOf called on non-object
Now there's no confusion between expression #2 and #3
Or you can just make your own function like so:
function isInstanceOf(obj, clazz){
return (obj instanceof eval("("+clazz+")")) || (typeof obj == clazz.toLowerCase());
};
usage:
isInstanceOf('','String');
isInstanceOf(new String(), 'String');
These should both return true.
Just curious:
4 instanceof Number => false
new Number(4) instanceof Number => true?
Why is this? Same with strings:
'some string' instanceof String returns false
new String('some string') instanceof String => true
String('some string') instanceof String also returns false
('some string').toString instanceof String also returns false
For object, array or function types the instanceof operator works as expected. I just don't know how to understand this.
[new insights]
Object.prototype.is = function() {
var test = arguments.length ? [].slice.call(arguments) : null
,self = this.constructor;
return test ? !!(test.filter(function(a){return a === self}).length)
: (this.constructor.name ||
(String(self).match ( /^function\s*([^\s(]+)/im )
|| [0,'ANONYMOUS_CONSTRUCTOR']) [1] );
}
// usage
var Newclass = function(){}; // anonymous Constructor function
var Some = function Some(){}; // named Constructor function
(5).is(); //=> Number
'hello world'.is(); //=> String
(new Newclass()).is(); //=> ANONYMOUS_CONSTRUCTOR
(new Some()).is(); //=> Some
/[a-z]/.is(); //=> RegExp
'5'.is(Number); //=> false
'5'.is(String); //=> true
value instanceof Constructor is the same as Constructor.prototype.isPrototypeOf(value) and both check the [[Prototype]]-chain of value for occurences of a specific object.
Strings and numbers are primitive values, not objects and therefore don't have a [[Prototype]], so it'll only work if you wrap them in regular objects (called 'boxing' in Java).
Also, as you noticed, String(value) and new String(value) do different things: If you call the constructor functions of the built-in types without using the new operator, they try to convert ('cast') the argument to the specific type. If you use the new operator, they create a wrapper object.
new String(value) is roughly equivalent to Object(String(value)), which behaves the same way as new Object(String(value)).
Some more on types in JavaScript: ECMA-262 defines the following primitive types: Undefined, Null, Boolean, Number, and String. Additionally, there is the type Object for things which have properties.
For example, functions are of type Object (they just have a special property called [[Call]]), and null is a primitive value of type Null. This means that the result of the typeof operator doesn't really return the type of a value...
Aditionally, JavaScript objects have another property called [[Class]]. You can get it via Object.prototype.toString.call(value) (this will return '[objectClassname]'). Arrays and functions are of the type Object, but their classes are Array and Function.
The test for an object's class given above works when instanceof fails (e.g. when objects are passed between window/frame boundaries and don't share the same prototypes).
Also, you might want to check out this improved version of typeof:
function typeOf(value) {
var type = typeof value;
switch(type) {
case 'object':
return value === null ? 'null' : Object.prototype.toString.call(value).
match(/^\[object (.*)\]$/)[1]
case 'function':
return 'Function';
default:
return type;
}
}
For primitives, it will return their type in lower case, for objects, it will return their class in title case.
Examples:
For primitives of type Number (eg 5), it will return 'number', for wrapper objects of class Number (eg new Number(5)), it will return 'Number';
For functions, it will return 'Function'.
If you don't want to discern between primitive values and wrapper objects (for whatever, probably bad reason), use typeOf(...).toLowerCase().
Known bugs are some built-in functions in IE, which are considered 'Object' and a return value of 'unknown' when used with some COM+ objects.
You may try to evaluate:
>>> typeof("a")
"string"
>>> typeof(new String("a"))
"object"
>>> typeof(4)
"number"
>>> typeof(new Number(4))
"object"
As stated in Christoph's answer, string and number literals are not the same as String and Number objects. If you use any of the String or Number methods on the literal, say
'a string literal'.length
The literal is temporarily converted to an object, the method is invoked and the object is discarded.
Literals have some distinct advantages over objects.
//false, two different objects with the same value
alert( new String('string') == new String('string') );
//true, identical literals
alert( 'string' == 'string' );
Always use literals to avoid unexpected behaviour!
You can use Number() and String() to typecast if you need to:
//true
alert( Number('5') === 5 )
//false
alert( '5' === 5 )
In the case of primitive numbers, the isNaN method could also help you.
This is a nuance of Javascript which I've found catches some out. The instanceof of operator will always result in false if the LHS is not an object type.
Note that new String('Hello World') does not result in a string type but is an object. The new operator always results in an object. I see this sort of thing:
function fnX(value)
{
if (typeof value == 'string')
{
//Do stuff
}
}
fnX(new String('Hello World'));
The expectation is that "Do Stuff" will happen but it doesn't because the typeof the value is object.
In JavaScript is there any difference between using String() and new String()?
console.log(String('word')); // word
console.log(new String('word')); // word
Using the String() constructor without new gives you the string (primitive) value of the passed parameter. It's like boxing the parameter in a native object if necessary (like a Number or Boolean), and then calling .toString() on it. (Of course if you pass a plain object reference it just calls .toString() on that.)
Calling new String(something) makes a String instance object.
The results look the same via console.log() because it'll just extract the primitive string from the String instance you pass to it.
So: just plain String() returns a string primitive. new String(xyz) returns an object constructed by the String constructor.
It's rarely necessary to explicitly construct a String instance.
String() returns a string primitive and new String() returns a Object String. This has some real consequences for your code.
Using String() returns 'true' with other primitives both with == and === operator.
Using String() gives you a primitive so it cannot use the "instanceOf" method to check its type. You can check only value type with "typeof" operator
Using new String() with "instanceOf" method with String or Object prototypes - both assert to true.
Using new String() will return 'true' with string primitives only by calling valueOf() method. String() has also this method and returns true when compared to string of the same value.
Using new String() allows you to add some other properties and methods to the Object to allow more complex behaviour.
From my coding experience you should avoid using new String() if you have no need for adding special methods to your String Object.
var x = String('word');
console.log(typeof x); // "string"
var y = new String('word');
console.log(typeof y); // "object"
// compare two objects !!!
console.log(new String('') === new String('')) // false!!!
// compare with string primitive
console.log('' == String('')) // true
console.log('' === String('')) // true
//compare with string Object
console.log('' == new String('')) // true
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
console.log('' === new String('')) // false !!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// instance of behavior
console.log(x instanceof String); // false
console.log(x instanceof Object); // false
// please note that only new String() is a instanceOf Object and String
console.log(y instanceof String); // true
console.log(y instanceof Object); // true
//valueOf behavior
console.log('word' == x.valueOf()); // true
console.log('word' === x.valueOf()); // true
console.log('word' == y.valueOf()); // true
console.log('word' === y.valueOf()); // true
//create smart string
var superString = new String('Voice')
superString.powerful = 'POWERFUL'
String.prototype.shout = function () {
return `${this.powerful} ${this.toUpperCase()}`
};
console.log(superString.shout()) //"POWERFUL VOICE"
Strings returned from String calls in a non-constructor context (i.e., without using the new keyword) are primitive strings.
Strings created with new String() (constructor mode) is an object and can store property in them.
Demonstrating the difference:
var strPrimitive = String('word');
strPrimitive.prop = "bar";
console.log(strPrimitive.prop); // undefined
var strObject = new String('word');
strObject.prop = "bar";
console.log(strObject.prop); // bar
Here is an example in addition to the good answers already provided:
var x = String('word');
console.log(typeof x); // "string"
var y = new String('word');
console.log(typeof y); // "object"
The exact answer to your question is here in the documentation.
String literals (denoted by double or single quotes) and strings
returned from String calls in a non-constructor context (i.e., without
using the new keyword) are primitive strings.
Generally it's not recommended to use constructor functions (i.e. using new keyword) because it can lead to unpredictable results.
For example:
if (new Number(0)) { //
console.log('It will be executed because object always treated as TRUE in logical contexts. If you want to treat 0 as falsy value then use Number(0)')
}
Also, as mentioned above, there is another potential problem:
typeof 0; // number
typeof Number(0) // number
typeof new Number(0) // object
"foo" instanceof String //=> false
"foo" instanceof Object //=> false
true instanceof Boolean //=> false
true instanceof Object //=> false
false instanceof Boolean //=> false
false instanceof Object //=> false
12.21 instanceof Number //=> false
/foo/ instanceof RegExp //=> true
// the tests against Object really don't make sense
Array literals and Object literals match...
[0,1] instanceof Array //=> true
{0:1} instanceof Object //=> true
Why don't all of them? Or, why don't they all not?
And, what are they an instance of, then?
It's the same in FF3, IE7, Opera, and Chrome. So, at least it's consistent.
Primitives are a different kind of type than objects created from within Javascript. From the Mozilla API docs:
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)
I can't find any way to construct primitive types with code, perhaps it's not possible. This is probably why people use typeof "foo" === "string" instead of instanceof.
An easy way to remember things like this is asking yourself "I wonder what would be sane and easy to learn"? Whatever the answer is, Javascript does the other thing.
I use:
function isString(s) {
return typeof(s) === 'string' || s instanceof String;
}
Because in JavaScript strings can be literals or objects.
In JavaScript everything is an object (or may at least be treated as an object), except primitives (booleans, null, numbers, strings and the value undefined (and symbol in ES6)):
console.log(typeof true); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof function () {}); // function
As you can see objects, arrays and the value null are all considered objects (null is a reference to an object which doesn't exist). Functions are distinguished because they are a special type of callable objects. However they are still objects.
On the other hand the literals true, 0, "" and undefined are not objects. They are primitive values in JavaScript. However booleans, numbers and strings also have constructors Boolean, Number and String respectively which wrap their respective primitives to provide added functionality:
console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0)); // object
console.log(typeof new String("")); // object
As you can see when primitive values are wrapped within the Boolean, Number and String constructors respectively they become objects. The instanceof operator only works for objects (which is why it returns false for primitive values):
console.log(true instanceof Boolean); // false
console.log(0 instanceof Number); // false
console.log("" instanceof String); // false
console.log(new Boolean(true) instanceof Boolean); // true
console.log(new Number(0) instanceof Number); // true
console.log(new String("") instanceof String); // true
As you can see both typeof and instanceof are insufficient to test whether a value is a boolean, a number or a string - typeof only works for primitive booleans, numbers and strings; and instanceof doesn't work for primitive booleans, numbers and strings.
Fortunately there's a simple solution to this problem. The default implementation of toString (i.e. as it's natively defined on Object.prototype.toString) returns the internal [[Class]] property of both primitive values and objects:
function classOf(value) {
return Object.prototype.toString.call(value);
}
console.log(classOf(true)); // [object Boolean]
console.log(classOf(0)); // [object Number]
console.log(classOf("")); // [object String]
console.log(classOf(new Boolean(true))); // [object Boolean]
console.log(classOf(new Number(0))); // [object Number]
console.log(classOf(new String(""))); // [object String]
The internal [[Class]] property of a value is much more useful than the typeof the value. We can use Object.prototype.toString to create our own (more useful) version of the typeof operator as follows:
function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
console.log(typeOf(true)); // Boolean
console.log(typeOf(0)); // Number
console.log(typeOf("")); // String
console.log(typeOf(new Boolean(true))); // Boolean
console.log(typeOf(new Number(0))); // Number
console.log(typeOf(new String(""))); // String
Hope this article helped. To know more about the differences between primitives and wrapped objects read the following blog post: The Secret Life of JavaScript Primitives
You can use constructor property:
'foo'.constructor == String // returns true
true.constructor == Boolean // returns true
typeof(text) === 'string' || text instanceof String;
you can use this, it will work for both case as
var text="foo"; // typeof will work
String text= new String("foo"); // instanceof will work
This is defined in the ECMAScript specification Section 7.3.19 Step 3: If Type(O) is not Object, return false.
In other word, if the Obj in Obj instanceof Callable is not an object, the instanceof will short-circuit to false directly.
I believe I have come up with a viable solution:
Object.getPrototypeOf('test') === String.prototype //true
Object.getPrototypeOf(1) === String.prototype //false
The primitive wrapper types are reference types that are automatically created behind the scenes whenever strings, numbers, or Booleans
are read.For example :
var name = "foo";
var firstChar = name.charAt(0);
console.log(firstChar);
This is what happens behind the scenes:
// what the JavaScript engine does
var name = "foo";
var temp = new String(name);
var firstChar = temp.charAt(0);
temp = null;
console.log(firstChar);
Because the second line uses a string (a primitive) like an object,
the JavaScript engine creates an instance of String so that charAt(0) will
work.The String object exists only for one statement before it’s destroyed
check this
The instanceof operator returns false because a temporary object is
created only when a value is read. Because instanceof doesn’t actually read
anything, no temporary objects are created, and it tells us the values aren’t
instances of primitive wrapper types. You can create primitive wrapper
types manually
For me the confusion caused by
"str".__proto__ // #1
=> String
So "str" istanceof String should return true because how istanceof works as below:
"str".__proto__ == String.prototype // #2
=> true
Results of expression #1 and #2 conflict each other, so there should be one of them wrong.
#1 is wrong
I figure out that it caused by the __proto__ is non standard property, so use the standard one:Object.getPrototypeOf
Object.getPrototypeOf("str") // #3
=> TypeError: Object.getPrototypeOf called on non-object
Now there's no confusion between expression #2 and #3
Or you can just make your own function like so:
function isInstanceOf(obj, clazz){
return (obj instanceof eval("("+clazz+")")) || (typeof obj == clazz.toLowerCase());
};
usage:
isInstanceOf('','String');
isInstanceOf(new String(), 'String');
These should both return true.
What are the use cases for doing new String("already a string")?
What's the whole point of it?
There's very little practical use for String objects as created by new String("foo"). The only advantage a String object has over a primitive string value is that as an object it can store properties:
var str = "foo";
str.prop = "bar";
alert(str.prop); // undefined
var str = new String("foo");
str.prop = "bar";
alert(str.prop); // "bar"
If you're unsure of what values can be passed to your code then I would suggest you have larger problems in your project. No native JavaScript object, major library or DOM method that returns a string will return a String object rather than a string value. However, if you want to be absolutely sure you have a string value rather than a String object, you can convert it as follows:
var str = new String("foo");
str = "" + str;
If the value you're checking could be any object, your options are as follows:
Don't worry about String objects and just use typeof. This would be my recommendation.
typeof str == "string".
Use instanceof as well as typeof. This usually works but has the disadvantage of returning a false negative for a String object created in another window.
typeof str == "string" || str instanceof String
Use duck typing. Check for the existence of one or more String-specific methods, such as substring() or toLowerCase(). This is clearly imprecise, since it will return a false positive for an object that happens to have a method with the name you're checking, but it will be good enough in most cases.
typeof str == "string" || typeof str.substring == "function"
Javascript creators created wrappers for basic types like string or int just to make it similar to java. Unfortunately, if someome makes new String("x") the type of the element will be "object" and not "string".
var j = new String("x");
j === "x" //false
j == "x" //true
String objects can have properties, while string primitives can not:
var aStringObject=new String("I'm a String object");
var aStringPrimitive="I'm a string primitive";
aStringObject.foo="bar";
console.log(aStringObject.foo); //--> bar
aStringPrimitive.foo="bar";
console.log(aStringPrimitive.foo); //--> undefined
And String objects can be inherited from, while string primitives can not:
var foo=Object.create(aStringObject);
var bar=Object.create(aStringPrimitive); //--> throws a TypeError
String objects are can only be equal to themselves, not other String objects with the same value, while primitives with the same value are considered equal:
var aStringObject=new String("I'm a String object");
var anotherStringObject=new String("I'm a String object");
console.log(aStringObject==anotherStringObject); //--> false
var aStringPrimitive="I'm a string primitive";
var anotherStringPrimitive="I'm a string primitive";
console.log(aStringPrimitive==anotherStringPrimitive); //--> true
You could implement overloading-like behavior:
function overloadedLikeFunction(anArgument){
if(anArgument instanceof String){
//do something with a String object
}
else if(typeof anArgument=="string"){
//do something with a string primitive
}
}
Or specify argument purpose:
function aConstructorWithOptionalArugments(){
this.stringObjectProperty=new String("Default stringObjectProperty value");
this.stringPrimitiveProperty="Default stringPrimitiveProperty value";
for(var argument==0;argument<arguments.length;argument++){
if(arguments[argument] instanceof String)
this.stringObjectProperty=arguments[argument];
if(typeof arguments[argument]=="string")
this.stringPrimitiveProperty=arguments[argument];
}
}
Or track objects:
var defaultStringValue=new String("default value");
var stringValue=defaultStringValue;
var input=document.getElementById("textinput") //assumes there is an text <input> element with id equal to "textinput"
input.value=defaultStringValue;
input.onkeypress=function(){
stringValue=new String(this.value);
}
function hasInputValueChanged(){
//Returns true even if the user has entered "default value" in the <input>
return stringValue!=defaultStringValue;
}
The existence of String objects and string primitives effectively gives you two string "types" in Javascript with different behaviors and, consequently, uses. This goes for Boolean and Number objects and their respective primitives too.
Beware, however, of passing string (or other) primitives as the value of this when using the function methods bind(), call() and apply(), as the value will be converted to a String object (or a Boolean or a Number object, depending on the primitive) before being used as this:
function logTypeofThis(){
console.log(typeof this);
}
var aStringPrimitive="I'm a string primitive";
var alsoLogTypeofThis=logTypeofThis.bind(aStringPrimitive);
console.log(typeof aStringPrimitive); //--> string;
logTypeofThis.call(aStringPrimitive); //--> object;
logTypeofThis.apply(aStringPrimitive); //--> object;
alsoLogTypeofThis(); //--> object;
And unexpected/counter-intuitive return types:
var aStringObject=new String("I'm a String object");
console.log(typeof aStringObject); //--> object
aStringObject=aStringObject.toUpperCase();
console.log(typeof aStringObject); //--> string
You could use instanceof if you really want to be paranoid:
if(typeof x === "string" || x instanceof String)
The instanceof operator will properly handle subclasses of String too:
obj instanceof ConstructorFunction works by checking if ConstructorFunction.prototype is in the prototype chain of obj.
I don't think I've ever actually used the String class in JavaScript but there's nothing wrong with being paranoid and aiming for correctness.
In most cases you work alone and can control yourself, or on a team and there is a team guideline, or can see the code you're working with, so it shouldn't be a problem. But you can always be extra safe:
var obj = new String("something");
typeof obj; // "object"
obj = ""+obj;
typeof obj; // "string"
Update
Haven't though much about the implications of this, although it seems to work:
var obj = new String("something"), obj2 = "something else";
obj.constructor === String; // true
obj2.constructor === String; // true
Of course, you should check if the object has a constructor (i.e. if it is an object).
So you could have:
isString(obj) {
return typeof obj === "string" || typeof obj === "object" && obj.constructor === String;
}
Although I suggest you just use typeof and "string", a user should know to pass through a normal string literal.
I should note this method is probably susceptible to someone creating an object and setting it's constructor to be String (which would indeed be completely obscure), even though it isn't a string...
Object.prototype.toString.call(aVariable) == '[object String]'
You can also convert a String object (along with anything else) to a String primitive with toString:
var str = new String("foo");
typeof str; // object
typeof str.toString(); // string
Thanks All, Even after so many years this question doesn't have a precise answer.
JavaScript has got two type of data,
Primitives :- string (let a = 'testStr'), number, boolean, null, undefined,symbol and bigint.
Objects :- Everything else (Functions, Arrays, JS Objects, ....)
Its the way JS is designed for efficiency(you know JS on V8 is like rocket) that all primitives are immutable(changing a str of num creates a new variable behind the scene) and objects are mutable.
To support primitives to used like objects JS has this feature of AutoBoxing. So when we use any method (say toString() for number) with primitives, JS automatically converts it to the corresponding Object and then executes the method and converts it back to primitive.
Normally we should never use the constructor(with new) and use it like a primitive only(let str = 'testStr'). Using constructor object instead of primitive might cause slow execution and complications.
Why do you need to check if it is string?
Just check if it is defined or null, and otherwise defensively convert it to any type you want, either the var bar = new String(foo); or var bar = "" + foo;.