What's the difference between using instanceof and checking the constructor? - javascript

Why do the following two lines return different results?
("test" instanceof String) // returns false
("test".constructor == String) // returns true
Tested in the console of chrome version 28.0.1500.95 m
Does it work slightly differently for native types?

constructor is just a property of the internal [[prototype]] property, that can easily be manipulated:
function A(){}
function B(){}
A.prototype.constructor = B;
var a = new A();
console.log(a.constructor); //B
The instanceof operator however checks the internal prototype chain and is not so easily to be fooled, even if you change the complete prototype property of the constructor function:
function A(){}
function B(){}
A.prototype = B.prototype;
var a = new A();
console.log(a instanceof A); //true
console.log(a instanceof B); //false
So, why is "test" instanceof String === false but ("test".constructor == String) === true?
First of all, "test" is a primitive and primitives are never an instance of anything. What actually happens when you use instanceof is that the internal [[HasInstance]] method of the constructor is called with the possible instance as an argument. So a instanceof A translates roughly to:
`A.[[HasInstance]](a)`
The ECMA Specs have this to say to [[HasInstance]]: http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.3
[[HasInstance]] (V)
Assume F is a Function object.
When the [[HasInstance]] internal method of F is called with value V,
the following steps are taken:
If V is not an object, return false.
....
In other words: If the left hand side of instanceof is not an object, the operator will return false.
("test".constructor == String) === true works for a different reason: If you try to access a property of a primitive, the primitive will be temporarily converted into an object. So "test".constructor is roughly equal to:
(new String("test")).constructor
in which case you are actually creating an object, with a constructor function and requesting the constructor property afterward. So it is no surprise, that it will return String.

The main difference is that instanceof inspects the object's prototype chain whereas checking the constructor only checks to see if it was created from the same constructor.
Example:
function MyObject() {
this.sayHi = function() { alert('Hi!'); }
}
var x = new MyObject();
alert(x.constructor === Object);
alert(x instanceof Object);

Related

Changing object prototype

I have the following 2 functions:
function Dog() {}
function Cat() {}
I set Dog.prototype = new Cat()
I then create a dog instance:
let dog = new Dog();
Why is dog instanceof Dog === true. I understand why dog instanceof Cat === true because I just set it to Cat's prototype but how is there still some reference to Dog prototype when it has been overridden even before the instance was created? How would I make make dog instanceof Dog === false?
As mentioned in MDN docs
The instanceof operator tests whether the prototype property of a
constructor appears anywhere in the prototype chain of an object.
That means instanceof will check the prototype property of the constructor with the __proto__ of the Object, not the value that prototype is holding. You can check this as following
console.log(Dog.prototype === dog.__proto__) // prints -> true
console.log(Dog.prototype === Object.getPrototypeOf(dog)) // prints -> true
What you are doing is merely changing the prototypes's `value. It still is the same property.
Modified:
Take a look at simplified implementation on instanceof method
function instanceOf(object, constructor) {
return Object.getPrototypeOf(object) === constructor.prototype;
}
Here, you can see that instanceof returns true, if reference of Object.getPrototypeOf(object) is equal to constructor.prototype. In your case Dog.prototype is Cat, and Object.getPrototypeOf(dog) is also Cat. That's why instanceof will always return true.
Reference
Link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
Search for Object.getPrototypeOf(o) === C.prototype

Javascript Prototype property : Prototype based Inheritance

I'm confused with Javascript's prototype property.
See the below Code.
var s = 12;
var s1 = new String();
console.log(s.constructor); // Outputs: Number() { [native code] }
console.log(s instanceof String); // Outputs: false
console.log(s instanceof Object); // Outputs: false
//console.log(toString() in s);
console.log(s.isPrototypeOf(Object)); // Outputs: false
//console.log(s.prototype.isPrototypeOf(Object));
console.log(s.hasOwnProperty ("toString")); // Outputs: false
console.log(s.toString()); // // Outputs: 12
// My Question is how does toString() function is been called, where does it falls int the prototype chain. Why is it not showing undefined.
console.log(s1.constructor); // Outputs: Number() { [native code] }
console.log(s1 instanceof String); // Outputs: true
I understand that when we create an object by using {} or constructor (new String()) above, it inherits from Object.prototype. And thats why console.log(s1 instanceof String); // Outputs: true and thus we're able to call toString() on s1. But i'm confused with what happens in the case of var x = "someString" or var x = something.
Thanks for your time.
There's a difference between string primitive values (like "hello world") and String objects. Primitive types — strings, numbers, booleans — are not objects.
When primitive values are used like objects, with the . or [] operators, the runtime implicitly wraps the values in objects via the corresponding constructors (String, Number, Boolean). Primitive values don't have properties, but because of that automatic wrapping you can do things like
var n = "hello world".length;
and it works.

What is the difference between `this instanceof String` and `"foo" instanceof String`?

I'm extending Object like this:
Object.prototype.is_a = function (x) {
return this instanceof x;
}
All works as expected
"foo".is_a(String) // true
"foo".is_a(Object) // true
"foo".is_a(Array) // false
"foo".is_a(Function) // false
"foo".is_a(Boolean) // false
"foo".is_a(Date) // false
"foo".is_a(Number) // false
"foo".is_a(RegExp) // false
but, when
"foo" instanceof String // false
this keyword on the is_a() function is same as foo right? Why does it return different results?
First of all, you cannot apply instanceof to primitive values, that's why
"foo" instanceof String
returns false. Primitives are not objects and hence cannot be an instance of a constructor function. *
So why does it seem to work inside the is_a method?
In non-strict mode, the value of this inside a function is always going to be an object (step 3). If this value is not an object, it is implicitly converted to one. You can test this with console.log(typeof this).
That means that the string primitive "foo" is converted to an String object new String("foo") and that's why you can use instanceof on it.
In strict mode, the value of this doesn't have to be an object and is not automatically converted (step 1). Your method would fail in that case:
> Object.prototype.is_a = function (x) {
'use strict';
return this instanceof x;
}
> "foo".is_a(String)
false
*: That's a very simplified explanation. In reality, the instanceof operator delegates the evaluation to the constructor function's internal [[HasInstance]] method, which is defined to return false if the passed value is not an object.
String literals aren't the same as String objects (MDN). It appears that the string literal (which is a string primitive) is automatically boxed into an object when it's used as the binding context of a function (i.e. when it's this inside a function):
>>> typeof "foo"
"string"
>>> Object.prototype.type_of = function (x) {
return typeof this;
}
function (x) {
return typeof this;
}
>>> "foo".type_of()
"object"
That explains your instanceof behavior, as well. This behaves as you might expect:
>>> new String("foo") instanceof String
true
>>> new String("foo") instanceof Object
true
>>> new String("foo").is_a(String)
true
>>> new String("foo").is_a(Object)
true
>>> new String("foo").is_a(Array)
false
JavaScript has both primitive and object versions of strings, numbers and booleans. String literals define primitives rather than objects. If you did typeof "foo", you would get "string" rather than "object". But when you access a property of the string, it creates a temporary String object from the primitive string and then accesses the corresponding property of that object, so it this instanceof String is true inside that temporary String object's method.
In order to test whether something is a string while accounting for both primitives and objects, you need to test typeof foo === "string" || foo instanceof String.
instanceof needs an object defined, this example returns true:
var f = new String("foo");
alert( f instanceof String);
This is more similar to your example:
alert( new String("foo") instanceof String);

Objects, prototypes and cosntructors in javaScript

This is a kind of question very debated, but I think the reason is the lack of good documentation and good books on the subject.
When I study a language I do a lot of digging even if some of my tests are absurd, but I think the only way to understand things is doing all kinds of experiments.
I'm beginning with JavaScript and as much I code as more I'm confused.
Let's view the code (forget the no-senses by now and consider only the outputs):
function Vehicle()
{
this.color = 'Blue'
}
var car = new Vehicle()
console.log('Vehicle.constructor: ', Vehicle.constructor)
console.log('car.constructor: ', car.constructor)
console.log('Vehicle.prototype: ', Vehicle.prototype)
console.log('car.prototype: ', car.prototype)
console.log('Vehicle.constructor.prototype: ', Vehicle.constructor.prototype)
console.log('car.constructor.prototype: ', car.constructor.prototype)
console.log('Vehicle.prototype.constructor: ', Vehicle.prototype.constructor)
console.log('car.prototype.constructor: ', car.prototype.constructor)
Output:
Vehicle.constructor: Function()
car.constructor: Vehicle()
Vehicle.prototype: Vehicle {} // curly braces here
car.prototype: undefined
Vehicle.constructor.prototype: function()
car.constructor.prototype: Vehicle {} // curly braces here
Vehicle.prototype.constructor: Vehicle()
TypeError: car.prototype is undefined
My conclusions:
Vehicle.prototype == car.constructor.prototype == Vehicle {} // curly braces here
Vehicle.prototype.constructor == car.constructor == Vehicle() // parenthesis here
Vehicle.constructor == Function() // uppercase 'F'
Vehicle.constructor.prototype == function() // lowercase 'f'
car.prototype == undefined // undefined but not reported as error
car.prototype.constructor // Type error. Here 'car.prototype' is reported as an error
Now let's consider the similar code:
var car = {color: 'Blue'}
console.log('car.constructor: ', car.constructor)
console.log('car.prototype: ', car.prototype)
console.log('car.constructor.prototype: ', car.constructor.prototype)
console.log('car.prototype.constructor: ', car.prototype.constructor)
Output:
car.constructor: Object()
car.prototype: undefined
car.constructor.prototype: Object {} // curly braces here
TypeError: car.prototype is undefined
As we can see, here 'car.prototype' is only undefined, but 'car.prototype.constructor' is undefined and also 'TypeError'
The code above is tested in Firebug. I don't know this is Firebug's fault or JavaScript fault.
All of this puzzled me.
If this is OOP in JavaScript I think this is more ODP - Object (Dis)oriented Programming
EDIT
1) Why car.prototype is undefined when car.prototype.constructor is TypeError
2) Why both functions and objects have constructors and prototypes (see code above)?
3) What the meaning of this:
Vehicle.constructor.prototype: function()
Vehicle.prototype.constructor: Vehicle()
car.constructor.prototype: Vehicle {}
You should remember forever: Every function in JavaScript is actually a Function object, as Function inherited from Object, any function is Object too. So, keeping in mind this sentence, look at this:
(function f(){}) instanceof Function; // true
(function f(){}) instanceof Object; // true, as Function is an instance of Object
({}) instanceof Object; // true
({}) instanceof Function; // false!
Function.prototype instanceof Object; // true
Function instanceof Object; // true, as all objects in JS are inherited from Object
Object instanceof Function; // true, as Object is a constructor function, therefor:
Function instanceof Function; // true
Object instanceof Object; // true, but:
Date instanceof Date; // false
Function.prototype.constructor === Function; // true
Function.constructor === Function; // true
typeof Object === 'function'; // true, as Object is a constructor function
So, different braces indicate that prototype is always an object (curly braces), if it is defined, and constructor is always a function. That's all.
Any time you declare an object using object literal notation
var newObject = {foo: 'bar'};
You are creating an object that inherits from 'Object()' and has no prototype of it's own.
Notice when you call 'car.constructor' it returns 'Object()'. This is because that is the constructor JS uses in object literal notation.
When you call 'car.prototype' it is undefined because object literals have no prototype of their own.
When you call 'car.constructor.prototype' it returns an empty object since that is the essentially the value of 'Object()'. It just creates objects.
in order for your objects to have their own prototypes you must establish a constructor and use
'new myObject()' to declare your objects.
I hope I've helped answer your question. Here are a few links that have more info:
Adding Prototype to JavaScript Object Literal
http://doctrina.org/Javascript-Objects-Prototypes.html
http://yehudakatz.com/2011/08/12/understanding-prototypes-in-javascript/

instanceof - javascript inconsistency in Object-Oriented javascript by Stoyan Stefanov

In Stoyan Stefanov's book Object-Oriented javascript, on page 103 he has the following. However when I try this, I get a different result with h instanceof Object. Am I missing something, has something in JS changed since or is this an error in the book.
>>> function Hero(){}
>>> var h = new Hero();
>>> var o = {};
>>> h instanceof Hero;
true
>>> h instanceof Object;
false //true in Google Chrome
>>> o instanceof Object;
true
If that's what the book says, then the book
is incorrect. (And searching the book content in Amazon.com confirms the error.)
Your true result that you get in Google Chrome is the correct result.
While the h object inherits from the .prototype on the Hero function, that .prototype inherits from the .prototype on the Object function. This means that h inherits both from Hero.prototype and Object.prototype, and is considered an instance of both constructors.
The only way it wouldn't be would be if Hero.prototype was an object that did not inherit from Object.prototype. But in that example, it uses the default object, so it does indeed inherit.
Using the instanceof operator you don't test whether something was created by a certain constructor, but whether something inherits from a certain object (whether a certain object is in the prototype chain of something). foo instanceof F has exactly the same result as a recursive* Object.getPrototypeOf(foo) === F.prototype
var F = function() {};
var foo = new F();
foo instanceof F // true
Object.getPrototypeOf(foo) === F.prototype // true
F.prototype = {}; // changed the prototype of F
foo instanceof F // false
Object.getPrototypeOf(foo) === F.prototype // false
foo instanceof Object // true
Object.getPrototypeOf(Object.getPrototypeOf(foo)) === Object.prototype // true
With that in mind, it is pretty obvious that if you don't change the prototype of a function to an object which doesn't inherit from Object.prototype, all the instances constructed with that function as constructor will inherit from Object.prototype, so they will be instances of Object.
F.prototype = Object.create(null);
var bar = new F();
bar instanceof F // true
bar instanceof Object // false
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
instanceof shim (just theoretical purposes, there is no practical use for it):
function instanceOf(object, constructor) {
if (!object) return false;
var object = Object.getPrototypeOf(object);
if (object === constructor.prototype) return true;
return instanceOf(object, constructor);
}

Categories