JavaScript: Object inheriting from Function.prototype
I have tested James Shore Object Playground and I can see that all methods inherit from Function.prototype, including methods on the global Object.prototype. How it works? Isn't that a cool circular? I mean ... isn't Function.prototype "itself" an Object.prototype object? So how does Object have something of Function.prototype? Isn't just a subtype of an object a function? Should the object essentially contain these behaviors anyway? Why is this inheritance necessary?
source to share
TL; DR
Object.prototype is the last in the prototype chain and it doesn't inherit anything. The Object constructor is the one that inherits from Function.prototype , because it's just a function; this is a function instance.
Long version
Since your question is a general one, I will try to cover several topics and hopefully you will answer your own question. Here are the topics I'll try to describe:
- Two ways to use the word "prototype".
- How classes are created in JavaScript.
- How Function and Object constructors are related .
Note. ... It can be difficult and confusing at times to explain how JavaScript works. I hope you get something out of this though.
Two ways to use the word "prototype"
The word "prototype" can be a little confusing in JavaScript. This is because there are at least two ways to use this word depending on the context:
1) "Object prototype another object
Another object's prototype object is also referred to as an "internal prototype", denoted as [[Prototype]] or __proto__
; they all mean the same thing. For example, consider the array: nums = [9, 8, 7];
. We say that it nums
is an array ... but why?
- We say it's an array because it's a constructor instance
Array
(constructors are just functions, except we use them with the new keyword ). - We also say that it is an array because its prototype object (internal prototype aka) is an object contained within a property
Array.prototype
.
2) "Property of the prototype of the constructor function"
Continuing the example of the array nums
, Array constructor function has a property with the name prototype
, and we can access it as follows: Array.prototype
. This property is an "internal prototype" Array instances and provides all the methods that we use to call arrays - such as forEach
, push
, pop
, join
etc.
So, along the same lines, the internal prototype of my function foo()
or any other function is an object that is contained within a property Function.prototype
; in other words, Function.prototype
it is any "internal prototype" function of an object. In addition, the Function constructor can be said to have a prototype property, which is ultimately the "internal prototype" of all functions.
Where do I get what we are talking about one thing (prototype) in two different ways. In the first case, we say: "prototype / internal prototype" of the object, and in the second - "constructor prototype property".
How classes are created in JavaScript
In JavaScript , constructor functions are similar to classes in other programming languages. Well, not quite. In fact, to resemble classes, JavaScript uses a combination of a constructor function and another object called a prototype... In fact, every JavaScript function automatically acquires a prototype property because a function can be used as a constructor or simply as a function. When a function is not used as a constructor, its prototype property is not used for anything, and it just dangles there like a useless property.
In classical languages, a class contains both instance variables and instance methods; however, in JavaScript, a constructor function contains instance variables, and a prototype object contains instance methods.
Instance variables are unique to a specific instance of a constructor function (they contain specific instance data), and instance methods are shared by all instances. In other words, all instances can execute instance methods, but cannot access variables from each other.
Thus, all objects in JavaScript are instances of their corresponding constructor functions. For example, an array such as [1,2,3]
is a constructor instance function Array() {}
. Objects like {key: 'value'}
are constructor instances function Object() {}
. JavaScript functions like alert()
are constructor instances function Function() {}
... etc.
Again, all constructor functions in JavaScript have a property prototype
, and this property includes methods that inherit constructor instances.
Example:
// Person constructor to create people instances
function Person(name, age) {
// Every instance has its own "instance variables", a.k.a. properties.
this.name = name;
this.age = age;
}
// The "instance methods"
Person.prototype = {
greet: function() {
return 'Hello ' + this.name;
},
//...
};
// Joe is an instance of the `Person` constructor, and Joe "prototype"
// is the `Person.prototype` object. We call Joe "prototype" the
// "internal prototype".
var joe = new Person('Joe Doe', 44);
joe.name; //=> Joe Doe
joe.greet(); //=> Hello Joe Doe
How function and object constructors are related
Constructor Object
.
The Object constructor is similar to the Person constructor above, except that it creates instance instances instead of user instances.
Constructor Function
.
The Function constructor is similar to the Person and Object constructors above, except that it creates Function instances, in other words, it creates functions.
All constructors in JavaScript, such as Person
, Object
, Array
, Function
, String
, Boolean
, etc., are merely functions. Since they are functions, this means that they were created from new Function
internally in the language, and all functional methods such as call()
and apply()
refer to Function.prototype . In other words, Function.prototype is the prototype / internal prototype object of all functions, including constructors and the function itself Function
.
Output:
Do not confuse the constructor property prototype
, which includes methods that future instances will use, with the internal prototype of the constructor itself.
However, keep in mind that a constructor property prototype
is internal [[Prototype]] instances of that constructor. For example, Function.prototype
[[Prototype]] is internal to a constructor Object
, which makes sense, since a constructor Object
is another function (instance Function
).
For code output, take a look at how the Object and Function constructors are created inside JavaScript:
// Object constructor
// ==============================================
function Object() { /* ... */ }
// Object.keys()
// Object.observe()
// ...
// `Object.__proto__` (internal [[Prototype]])
// -----------------------------------------------
// Since `Object` is a function, it inherits all of Function
// instance methods (the ones inside of Function.prototype).
//
// In other words the `Object` constructor can use methods
// like `apply()`, `call()`, `bind()`, and more.
//
// So we can say that the Object prototype is the
// `Function.prototype` object.
Object.__proto__ = Function.prototype;
// `Object.prototype` (instance methods)
// -----------------------------------------------
// The Object `prototype` property is totally different from
// the `__proto__` property. This `prototype` property includes
// methods that all JavaScript objects inherit. So an object
// literal like `var obj = {}` or an array like `var arr = []`
// or even a function like `alert` can use these methods.
Object.prototype = {
constructor: Object,
hasOwnProperty: function() {},
isPrototypeOf: function() {},
//...
};
// Function constructor
// ==============================================
function Function() { /* ... */ }
// Function.call()
// Function.apply()
// ...
// [[Prototype]] + instance methods
// -----------------------------------------------
// Since `Function` is a function itself and at the same time
// the constructor for other JavaScript functions, its internal
// [[Prototype]] and the `prototype` property point to the same
// exact object.
Function.__proto__ = Function.prototype = {
apply: function() {},
call: function() {},
bind: function() {},
//...
// Just an object literal, so it inherits the
// Object instance methods.
__proto__: Object.prototype
};
Additional Resources
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model#Determining_instance_relationships
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
- https://es5.github.io/#x15.3.4
- http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-15.3.2.1 ; A prototype property is automatically generated for each function to ensure that the function will be used as a constructor.
- https://www.quora.com/In-JavaScript-what-is-the-logic-behind-the-data-structure-of- prototype-function- proto and-constructor? share = 1
source to share
What are prototypes?
JavaScript is a prototype-based language. This means there are technically no "classes". There are only prototypes that describe objects. Every object has a prototype. The prototype itself is actually an object. (Confused, huh? Don't think too hard about it, if you can't wrap it around you, it will click someday. Just know that prototypes are objects that you can change).
Before proceeding, I would like to point out that my code examples here are not following good or best practices. The code samples I've written are purely a demonstration or explanation of the concept.
Let's look at some code:
Object.toString(); // "[object Object]"
Object.prototype.toString(); // "[object Object]"
Object.hasOwnProperty('toString'); // true
typeof Object; // "function"
typeof Object.prototype // "object"
var obj = new Object();
obj.toString(); // "[object Object]"
obj.hasOwnProperty('toString'); // false
obj.toString = function() {
return 'My Object';
};
obj.toString(); // "My Object"
obj.hasOwnProperty('toString') // true
obj.__proto__.toString(); // "[object Object]"
typeof obj; // "object"
typeof obj.__proto__; // "object"
You may have also noticed what typeof Object
returns "function"
. This is because Object is actually a constructor method to create new objects. My object instance is actually typeof obj === "object"
.
Prototype chain
As you can see in the above code, Object
contains a method named toString
. But Object
there are no copies . obj
doesn't have a method of its own toString
. But you can still call toString
on obj
. JavaScript does inheritance by following the prototype chain.
I could overwrite obj.toString
to give obj
my own method toString
, but the property obj.__proto__
still has the original method toString
from it prototype
.
If the object in question does not contain its own property toString
, then the property will look at its prototype. If the native prototype does not contain a property toString
, then the search will continue the prototype chain until the property is found. If it is a prototype null
, then it is a property undefined
.
Is everything in JavaScript an object?
Yes, down at the very core, eventually in the prototype chain, every object is a JavaScript object. Including Functions
.
var func = function() {};
func.__proto__ //function Empty() {}
func.__proto__.__proto__ // Object {}
func.__proto__.isPrototypeOf(Object) // true
Thus, a function is an object in JavaScript. This is why you can attach properties to functions.
And some clarifications ...
all methods inherit from Function.prototype
No, all methods do not inherit from Function
. Methods Function
.
So, how does Object.prototype have something of the .prototype function?
The object does not inherit anything from the function. An object can use a function, such as a method toString
.
Object
kinda showcases a composite design structure. (Except that you can add properties to an object that references itself and / or creates circular references)
From [ http://en.wikipedia.org/wiki/Composite_pattern ]
In software development, a composite pattern is a design pattern for partitions. The composite pattern specifies that a group of objects should be treated the same as a single instance of an object. The purpose of a composite is to "arrange" objects in tree structures to represent the hierarchy of the whole.
Because it Object
contains several properties that are also Object
.
Is this the hinge? No, not at all. But this is definitely recursive.
You can read more about JavaScript prototypes here: http://blog.pluralsight.com/understanding-javascript-prototypes
Note that ES6 introduces actual classes to JavaScript. This is different from everything I explained above. ES6 class
is something I haven't played with yet.
source to share