What is the difference between typeof and instanceof and when should one be used vs. the other?
Use instanceof
for custom types:
var ClassFirst = function () {};
var ClassSecond = function () {};
var instance = new ClassFirst();
typeof instance; // object
typeof instance == 'ClassFirst'; // false
instance instanceof Object; // true
instance instanceof ClassFirst; // true
instance instanceof ClassSecond; // false
Use typeof
for simple built in types:
'example string' instanceof String; // false
typeof 'example string' == 'string'; // true
'example string' instanceof Object; // false
typeof 'example string' == 'object'; // false
true instanceof Boolean; // false
typeof true == 'boolean'; // true
99.99 instanceof Number; // false
typeof 99.99 == 'number'; // true
function() {} instanceof Function; // true
typeof function() {} == 'function'; // true
Use instanceof
for complex built in types:
/regularexpression/ instanceof RegExp; // true
typeof /regularexpression/; // object
[] instanceof Array; // true
typeof []; //object
{} instanceof Object; // true
typeof {}; // object
And the last one is a little bit tricky:
typeof null; // object
Differences between typeof and instanceof in JavaScript
typeof
is a construct that "returns" the primitive type of whatever you pass it.instanceof
tests to see if the right operand appears anywhere in the prototype chain of the left.
It is important to note that there is a huge difference between the string literal "abc"
, and the string object new String("abc")
. In the latter case, typeof
will return "object" instead of "string".
Why a number isn't instance of Number with typeof and instanceof?
JavaScript has number primitives and Number objects. A number primitive isn't instanceof
anything because it isn't an object, and only objects are "instances" of something ("instance" being a term of art from object oriented programming); so instanceof
is not useful for primitives.
That's where typeof
comes in. The result of typeof
for primitive numbers is "number"
.
Since instanceof
expects a constructor function as the right hand operand, you could have your ofType
function branch based on whether it gets a function or a string, using instanceof
if it's a function and typeof
if it's a string. Using your forEach
loop:
Array.prototype.ofType = function (type) {
let newArr = [];
if (typeof type === "string") {
this.forEach(i => typeof i === type ? newArr.push(i) : newArr );
} else {
this.forEach(i => i instanceof type ? newArr.push(i) : newArr );
}
return newArr;
};
But I wouldn't use forEach
for this, I'd use filter
:
Array.prototype.ofType = function (type) {
let newArr;
if (typeof type === "string") {
newArr = this.filter(i => typeof i === type);
} else {
newArr = this.filter(i => i instanceof type);
}
return newArr;
};
Also, I strongly recommend not adding enumerable properties to Array.prototype
, it breaks code that incorrectly uses for-in
loops on arrays. Use Object.defineProperty
instead:
Object.defineProperty(Array.prototype, "ofType", {
value(type) {
let newArr;
if (typeof type === "string") {
newArr = this.filter(i => typeof i === type);
} else {
newArr = this.filter(i => i instanceof type);
}
return newArr;
},
writable: true,
configurable: true,
enumerable: false // This is the default, so you could leave it off
});
Live Example:
Object.defineProperty(Array.prototype, "ofType", { value(type) { let newArr; if (typeof type === "string") { newArr = this.filter(i => typeof i === type); } else { newArr = this.filter(i => i instanceof type); } return newArr; }, writable: true, configurable: true, enumerable: false // This is the default, so you could leave it off});
console.log([1, "2", 3, "4"].ofType("number"));
console.log([new Date, "2", new Date, "4"].ofType(Date));
typeof and instanceof operators returns different information for the same var
You're confusing the primitive type string
and the type object for your object which is an instance of String
. They're different.
var s = "a"; // a string, typeof is "string"
var s = new String("a"); // an instance of String, typeof is "object"
What is the difference between the 'instanceof' and 'in' keywords?
The main difference is that instanceof
is a Java keyword, while obj in SomeClass
is an equivalent of SomeClass.isCase(obj)
method call as you mentioned in your question.
There is one major implication: instanceof
cannot be overridden and as Oracle docs says:
The
instanceof
operator compares an object to a specified type. You can use it to test if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface.
Source: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
Class.isCase(obj)
is implemented as follows:
/**
* Special 'Case' implementation for Class, which allows testing
* for a certain class in a switch statement.
* For example:
* <pre>switch( obj ) {
* case List :
* // obj is a list
* break;
* case Set :
* // etc
* }</pre>
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue is deemed to be assignable from the given class
* @since 1.0
*/
public static boolean isCase(Class caseValue, Object switchValue) {
if (switchValue instanceof Class) {
Class val = (Class) switchValue;
return caseValue.isAssignableFrom(val);
}
return caseValue.isInstance(switchValue);
}
Source: org/codehaus/groovy/runtime/DefaultGroovyMethods.java#L1121
As you can see based on the source code Groovy's obj in SomeClass
is not an alias to instanceof
, because it does a bit more. However, there is one important thing worth mentioning - you can override isCase()
implementation, but you can't change how instanceof
Java keyword behaves. Overriding Class.isCase()
may cause some damage to your code if you use it as an alternative to Java's instanceof
keyword.
typeOf without using getClass() or instanceof
Note that Java is statically typed language. There's no need to check the variable primitive type at runtime, because it's known at compile time and cannot change. For example, if you declare
int x = 5;
Then x
cannot be anything else other than int
, so trying to do something like typeof(x)
(like in some other languages) is meaningless.
You can generalize the variable type assigning it to the Object
reference type:
int x = 5;
Object obj = x;
But even in this case obj
will not be int
. In this case Java compiler will automatically box your x
to Integer
type, so obj.getClass().getName()
will return java.lang.Integer
and obj instanceof Integer
will return true.
Related Topics
How to Search JSON Tree with Jquery
How to Remove a Key from a JavaScript Object
Replacing Spaces with Underscores in JavaScript
How to Upload a File Using Jquery.Ajax and Formdata
Add Event Handler to HTML Element Using JavaScript
Select All Contents of Textbox When It Receives Focus (Vanilla Js or Jquery)
When to Use the JavaScript Mime Type Application/JavaScript Instead of Text/Javascript
How to Declare a Global Variable in a .Js File
What Is the Meaning of Symbol $ in Jquery
What Does ${} (Dollar Sign and Curly Braces) Mean in a String in JavaScript
Split String Only on First Instance of Specified Character
How to Log All Events Fired by an Element in Jquery
How to Set the Prototype of a JavaScript Object That Has Already Been Instantiated
Updating and Merging State Object Using React Usestate() Hook
How to Redefine a JavaScript Class's Method
What Does $.When.Apply($, Somearray) Do