Reputation: 5387
I read Douglas Crockford's JavaScript Good Parts book. In the book, method
is added to Function.prototype
a.
Function.prototype.method = function() {}
Function.prototype.method === Function.method; // true
b.
function MyClass() {}
MyClass.prototype.method = function() {}
MyClass.prototype.method == MyClass.method // false
infact MyClass.method
is undefined.
Why is it true in step a and false in step b?
please explain the following:
Object instanceof Function // true
Function instanceof Object // true
Object instanceof Object // true
Function instanceof Function // true
It is very confusing. please explain in simple words.
Upvotes: 3
Views: 82
Reputation: 55729
1a.
01 Function.prototype.method = function foo() {}
02 Function.prototype.method === Function.method; // true
This is the addition of a property to the object pointed to by the prototype
property of the built-in Function
function-object.
Function
is a built-in function-object instance named "Function".
Function
is therefore an object because functions are objects.
Because Function
is a function, it has a prototype
property. In this case, it is another function-object.
Line 1 above adds a property named method
to Function.prototype
pointing it to the function-object foo
(named for clarity).
Line 2 performs a test for reference equality between Function.prototype.method
(created in line 1) and the result of attempting to get the value associated with the property method
on the built-in Function
function-object. Property resolution in JavaScript is performed by searching the chain of objects linked by the prototype-chain.
So in line 2 Function.prototype.method
finds the property immediately as the method
property is located directly on Function.prototype
.
Also on line 2, Function.method
is not found immediately on Function
; the search then continues by looking at what is pointed at by the Function.__proto__
property (this is known as the prototype chain). The __proto__
reference in JavaScript automatically points to the prototype
property of the function that created it. In this case, because we are at the top of the prototype chain (this is the top-most function!), we have the unusual situation where the built-in Function
"created itself" (in reality Function
was created by the runtime itself, outside of userland code), meaning that both the prototype
and __proto__
properties - in this instance - point to the same object.
So the search for method
follows the __proto__
link, finds the same object pointed to by Function.prototype
, and finds a property method
there. Hence:
02 Function.prototype.method === Function.method; // true
1b.
01 function MyClass() {}
02 MyClass.prototype.method = function foo() {} // Named for clarity.
03 MyClass.prototype.method == MyClass.method // false
04 // infact MyClass.method is undefined.
This is normal userland code and we do not have the same problem of having to find the prototype for the top-most Function
object as in 1a.
As soon as it is declared (line 1 above), MyClass
gets a prototype
property like every function, pointing to an empty object instance.
Line 2 adds a property method
to this empty object instance and points it to a function foo
.
Line 3 tests for reference equality between foo
and the result of looking for a property method
on MyClass
. As before, to find method
on MyClass
a search is performed. It does not exist directly on MyClass
, so the object located on the property __proto__
is checked for a property named method (again, this is the prototype chain being traversed). In this case, just like 1a (and as for every object in JavaScript), the __proto__
points to the prototype
property of the function that created the object. Function-object MyClass
was created by the built-in Function
function-object, thus MyClass.__proto__
points to Function.prototype
(note, not MyClass.prototype
). It finds nothing there and continues the search up the prototype chain. It ultimately fails to find a property called method
, so returns undefined
.
Hence:
MyClass.prototype.method == MyClass.method // false
2.
Object instanceof Function // true
Object is a built-in constructor function-object for creating objects. Hence it is a function.
Function instanceof Object // true
instanceof
is an operator that returns true if the prototype property of the RHS object resides on the prototype chain of the LHS. The prototype chain of Function is:
Function.__proto__ -> Function.prototype
Function.prototype -> function f() {} // An ordinary function, named for clarity
f.__proto__ -> {} // An ordinary object. Let's call it 'o'.
So at the top of the prototype chain for functions, in order to avoid a circular loop, the prototype of the Object
constructor function is used as f.__proto__
(I call it f
here for clarity). Hence:
Function instanceof Object // true
Object instanceof Object // true
For this to be true Object.prototype
must be on the prototype chain of Object
.
Object.__proto__ -> Function.prototype
Function.prototype.__proto__ -> {} // This is 'o' from above.
So Function.prototype.__proto__ === Object.prototype
, hence:
Object instanceof Object // true
Function instanceof Function // true
This is true for the same explanation as 1a.
Upvotes: 1
Reputation: 82267
1.
a) You have just extended the Function built in object and now every instance of Function has that property attached, including the Function built in instance.
b) You have just extended MyClass with method and now every instance of MyClass has that method attached. However, MyClass is not an instance of MyClass and as a result that method is not present.
2.
These are standard built-in objects in the language. They are instances which can return an instance. With regards to Object, its prototype is shared with everything because everything derives from Object - it is best in general to avoid changing its prototype.
So that is why it seems that Function is an instance of Object. Everything is. Every instance derives from Function, so the Object instance is also an instance of Function. And that is the reverse.
There is a whole set of other fundamental objects, Object will not be an instance of Number for example, but Number is an instance of both Object and Function.
More on this list can be found at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
Shown below is only a small subset of these objects as the list contained some objects which are more than likely not of interest (such as URIError).
Upvotes: 4