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!