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;.
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
Warning: creating extensions to native object and/or properties is considered bad form, and is bound to cause problems. Do not use this if it is for code that you are not using solely for you, or if you don't know how to use it properly
I know you can use Object, String, Number, Boolean, etc. to define a method, something like this:
String.prototype.myFunction = function(){return this;} //only works on strings.
But what I need to be able to do is use that on any value, and access the value in the function.
I googled, and looked here, but couldn't find anything suitable.
2/18/15 Edit: Is there any workaround to having this be a property of any Object if I use Object.prototype?
Per Request, here is the current function that is used for isString()
function isString(ins) {
return typeof ins === "string";
}
Following on a few answers, I have come up with some code and errors caused by it.
Object.prototype.isString = function() {
return typeof this === "string";
}
"5".isString() //returns false
"".isString() //returns false
var str = "string"
str.isString() //returns false
A “dot operator function” is called a method. The cleanest way to create a method in JavaScript that can work on any data type is to create a wrapper. For example:
var Wrapper = defclass({
constructor: function (value) {
this.value = value;
},
isString: function () {
return typeof this.value === "string";
},
describe: function () {
if (this.isString()) {
alert('"' + this.value + '" is a string.');
} else {
alert(this.value + " is not a string.");
}
}
});
var n = new Wrapper(Math.PI);
var s = new Wrapper("Hello World!");
n.describe(); // 3.141592653589793 is not a string.
s.describe(); // "Hello World!" is a string.
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
By creating your own wrapper constructor you ensure that:
Your code doesn't mess with other peoples' code.
Other people's code doesn't mess with your code.
You keep the global scope and native prototypes clean.
Several popular JavaScript libraries like underscore and lodash create wrapper constructors for this very purpose.
First of all, why defining properties on Object (or other builtin types) is frowned upon - they show up in unexpected places. Here is some code that outputs the total number of feet some characters have:
var feetMap = {
jerry : 4,
donald : 2,
humpty: 0
}
function countFeet(feetMap) {
var allFeet = 0;
for (var character in feetMap) {
allFeet += feetMap[character];
}
return allFeet;
}
console.log('BEFORE DEFINITION', countFeet(feetMap));
Object.prototype.isString = function() {
return typeof this === "string";
};
console.log('AFTER DEFINITION', countFeet(feetMap));
Note how simply defining your isString function will influence the result of the countFeet function which now iterates over one unexpected property. Of course, this can be avoided if the iteration was protected with hasOwnProperty check, or if the property was defined as non-enumerable.
Another reason to avoid defining properties on builtin types it the possibility of collision. If everyone defined their own isNumber method that gave slightly different results depending on use cases - one could consider the string "42" a number and another could say it's not - subtile bugs would crop all over the place when people used multiple libraries.
The question is - why do you need a method that can affect any value type? A method should be something that is inherent to the class of objects it belongs to. Having an isString method makes no sense on a Number object - it simply doesn't have any relevance to Numbers.
What makes more sense is to have a function/method that can return the type of the value given to it as parameter:
var Util = Util || {};
Util.isString(value) {
return typeof value === "string";
}
Util.isString('test') // true
Util.isString(5) // false
The reason why your current code
Object.prototype.isString = function() {
return typeof this === "string";
}
"5".isString() //returns false
"".isString() //returns false
var str = "string"
str.isString() //returns false
isn't working is because when you access a property on a primitive value, JS creates a wrapper object of the apropriate types and resolves the property on that wrapper object (after which it throws it away). Here is an example that should elucidate it:
Object.prototype.getWrapper = function(){
return this;
}
console.log((5).getWrapper()); // Number [[PrimitiveValue]]:5
console.log("42".getWrapper()); // String [[PrimitiveValue]]:"42"
Note that the primitive value 5 and the object new Number(5) are different concepts.
You could alter your function to mostly work by returning the type of the primitive value. Also, don't forget to make it non-enumerable so it doesn't show up when you iterate over random Objects.
Object.defineProperty(Object.prototype, 'isString', {
value : function() {
return typeof this.valueOf() === "string";
},
enumerable : false
});
"5".isString() //returns true
"".isString() //returns true
var str = "string"
str.isString() //returns true
Object.prototype.isString = function() {
return typeof this === "string";
}
"5".isString() //returns false
"".isString() //returns false
var str = "string"
str.isString() //returns false
If anyone could explain a workaround for the function being a property of any object, and why the current method isn't working, I will provide 125 rep.
Answer:
Well in javascript, when you are calling a sub method/property of a object, like "myFunction" (object.myFunction or object["MyFunction"])
it will start to see if the object itself have it.
IF NOT: it will follow the prototype chain(like superclass in normal oop),
until it finds a "parent/superclass" with the method/property.
The last step in this prototype chain is Object.
If Object dosnt have the method, it will return "undefined".
When you extending the Object class itself it will alway look at
any object calling the method as a Object (In oop: All classes are also Object in addition the is own classtype)
This is like missing a "cast" in normal OOP.
So the reason why your function returns false is that its a "object" not a "string" in this context
Try making this function:
Object.prototype.typeString = function() {
return typeof this;
}
"5".typeString() //returns "object"
As everbody says it really bad idea to extend any of the native JS classes, but a workaround would start with something like this:
Object.prototype.objectTypeString = function(){
return Object.prototype.toString.call(this);
}
Here is a fiddle:
http://jsfiddle.net/fwLpty10/13/
Note that null dosnt have prototype and NaN (NotANumber) is condidered a Number!!!
This means that you will always need to check is a variable is null,
before calling this method!
Object.prototype.isString = function(){
return Object.prototype.toString.call(this) === "[object String]";
};
Final fiddle: http://jsfiddle.net/xwshjk4x/5/
The trick here is that this methods returns the result of the toString method, that are called with "this", which means that in the context of the toString method, the object you call it on, are its own class (not just any supertype in the prototype chain )
The code posted that extends the Object prototype will work, if corrected.
However, it makes an incorrect assumption about what this is inside the invoked method. With the posted code the following output is correct and to be expected (barring a few old implementation bugs);
"5".isString() //returns false
This is because JavaScript will "wrap" or "promote" the primitive value to the corresponding object type before it invokes the method - this is really a String object, not a string value. (JavaScript effectively fakes calling methods upon primitive values.)
Replace the function with:
Object.prototype.isString = function() {
return this instanceof String;
}
Then:
"5".isString() // => true (a string was "promoted" to a String)
(5).isString() // => false (`this` is a Number)
Another solution to this is also to use polymorphism; with the same "pitfalls"1 of modifying standard prototypes.
Object.prototype.isString = function () { return false; }
String.prototype.isString = function () { return true; }
1The concern of adding a new enumerable property to the global protoypes can be mitigated with using defineProperty which creates a "not enumerable" property by default.
Simply change
x.prototype.y = ..
to
Object.defineProperty(x.prototype, 'y', { value: .. })
(I am not defending the use of modifying the prototype; just explaining the original problematic output and pointing out a way to prevent the enumeration behavior.)
To show u some example:
String.prototype.myFunction = function() {
return this+"asd";
};
this function will add "asd" to each string when myFunction() is called.
var s = "123";
s = s.myFunction();
//s is now "123asd"
Before we start, few important statements to remember and be aware of (true for all string literal/primitive, String object, number literal/primitive, Number object etc.):
All objects in JavaScript are descended from Object and inherit methods and properties from Object.prototype – String, Number etc (much like Java).
JS has 6 primitive types – string, number, boolean, null, undefined and symbol
JS has their corresponding wrapper objects – String, Number, Boolean and Symbol
As you can see above, JS has string as a primitive as well an Object
Primitive is not of type Object.
String literal is a primitive and String object is of type Object.
The instanceof operator tests whether an object has in its prototype chain the prototype property of a constructor. (first condition to get TRUE here is that instanceof should be used against an Object or its subclass)
The typeof operator returns a string indicating the type of the unevaluated operand.
String as primitive:
String primitive or literal can be constructed in following ways:
var str1 = “Hello”;
var str2 = String(“Hello”);
typeof str1; //Output = "string"
typeof str2; //Output = "string"
str1 instanceof (String || Object) //Output = false because it is a primitive not object
str2 instanceof (String || Object) //Output = false because it is a primitive not object
String as Object:
String object can be constructed by calling its constructor from new object:
var str3 = new String(“Hello”);
typeof str3; //Output = "string"
str3 instanceof (String) //Output = true because it is a String object
str3 instanceof (Object) //Output = true because it is an Object
Above all may look little obvious but it was necessary to set the ground.
Now, let me talk about your case.
Object.prototype.isString = function() {
return typeof this === "string";
}
"5".isString() //returns false
"".isString() //returns false
var str = "string"
str.isString() //returns false
You are getting FALSE as o/p because of concept called as Auto-boxing. When you call any method on string literal then it gets converted to String object. Read this from MSDN - “Methods for String Literals”, to be sure in yourself.
So, in your prototype when you will check type using typeof then it will never be a literal (typeof == "string") because it is already converted into an object. That's the reason you were getting false, if you will check typeof for object then you will get true, which I am going to talk in detail below:
typeof will give information on what type of entity it is - an object or a primitive (string, number etc) or a function.
instanceof will give information on what type of JS Object it is - Object or String or Number or Boolean or Symbol
Now let me talk about solution which is provided to you. It says to do a instanceof check, which is 100% correct, but with a note that upon reaching your prototype it could be of object type or function type. So, the solution which I am providing below will give you a picture of the same.
My recommendation is to have a generic function which would return you the type of instance, and then you can do whatever you want based on if it is a Number or String etc. isString is good but then you have to write isNumber etc., so instead have a single function which will return you the type of instance and can even handle function type.
Below is my solution:
Object.prototype.getInstanceType = function() {
console.log(this.valueOf());
console.log(typeof this);
if(typeof this == "object"){
if(this instanceof String){
return "String";
} else if(this instanceof Boolean){
return "Boolean";
} else if(this instanceof Number){
return "Number";
} else if(this instanceof Symbol){
return "Symbol";
} else{
return "object or array"; //JSON type object (not Object) and array
}
} else if(typeof this == "function"){
return "Function";
} else{
//This should never happen, as per my knowledge, glad if folks would like to add...
return "Nothing at all";
}
}
Output:
new String("Hello").getInstanceType() //String
"Hello".getInstanceType() //String
(5).getInstanceType() //Number
(true).getInstanceType() //Boolean
Symbol().getInstanceType() //Symbol
var ddd = function(){}
var obj = {}
obj.getInstanceType() //object or array
var arr = []
arr.getInstanceType() //object or array
ddd.getInstanceType() //Function
($).getInstanceType() //Function, because without double quotes, $ will treated as a function
("$").getInstanceType() //String, since it came in double quotes, it became a String
To wrap up: Your 2 concerns as below
But what I need to be able to do is use that on any value, and access
the value in the function.
You can access the value in your function using this. In my solution you can see console.log(this.valueOf());
Is there any workaround to having this be a property of any Object if
I use Object.prototype?
You can achieve it from Object.prototype.getInstanceType as per above solution, and you can invoke it on any valid JS object and you will get the desired information.
Hope this helps!
From the MDN Description of Object:
All objects in JavaScript are descended from Object
So, you can add methods to Object.prototype, which can then be called on anything. For example:
Object.prototype.isString = function() {
return this.constructor.name === 'String';
}
console.log("hi".isString()); //logs true
console.log([].isString()); //logs false
console.log(5..isString()); //logs false
You could create this isX functions for each type of primitive there is, if you wanted. Either way, you can add methods to every type, since everything in JavaScript descends from an Object.
Hope that helps, and good luck :)
--edit--
I did want to point out that just because you can do this doesn't mean that you should. It's generally a bad practice to extend built-in functionality of JavaScript, even more so for a library that others will use. It depends on your use-case, though. Best of luck.
Discussions aside, that this is not good practice and not a common approach like the wrapper-constructor, you should achieve this with either asking for the constructor's name:
Object.defineProperty(Object.prototype, 'isString', {
value: function() { return this.constructor.name === "String"; }
});
or with the also already mentioned instanceof method:
Object.defineProperty(Object.prototype, 'isString', {
value: function() { return this instanceof String; }
});
Explanation why your method didn't work is taking care of in this post.
If you want your new defined property to be enumerable, configurable or writable, you should take a look at the docs for defineProperty.
As a few others have pointed out your code is almost correct expect for the typeof this === 'string' part which doesn't work due to JavaScript's quirky behavior when it comes to primitives vs. objects. One of the most robust ways to test if an object is a string is with Object.prototype.toString.call(this) === '[object String]' (check out this article). With that in mind you could simply write your implementation of isString like so:
Object.prototype.isString = function () {
return Object.prototype.toString.call(this) === '[object String]';
};
"abc".isString(); // ==> true
"".isString(); // ==> true
1..isString(); // ==> false
{}.isString(); // ==> false
This is because string literals are of native string type, not actually an instance of String object so, in fact, you cannot actually call any method from Object or String prototype.
What is happening is that when you try to call any method over a variable which type is string, Javascript is automatically coercing that value to a newly constructed String object.
So
"abc".isString();
Is the same as:
(new String("abc")).isString();
The side effect of that is that what you are receiving in your isString() method is an (variable of type) Object which, also, is an instance of the String object.
Maybe you could see it more clearly with a simplified example:
var a = "Hello";
console.log(typeof a); // string
var b = new String("Hello");
console.log(typeof b); // object
By the way, the best chance you have to detect string in your function, as many others said, is to check if it is an instance of the String object with:
foo instanceof String
If you want to also check over other possible types, you should do a double check like the following:
function someOtherFn(ins) {
var myType = typeOf ins;
if (myType == "object" && ins instanceof String) myType = "string";
// Do more stuf...
}
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.