I am trying to understand fully how prototypes work.
This is my definition of a prototype:
A built in property that all objects have (except the Base Object) which points to and references a 'proto{}' object which is a copy of another object whose properties and methods can then be referenced if not found in the original object.
Is that correct? Especially I'm wondering about the 'is a copy of another object' part - meaning that the JS Engine creates a stored copy of Object B in memory space which the prototype property of Object A points to for reference.
Now my questions about Object.create:
My understanding is that this method makes the prototype (or the object itself?) of whatever object it is used on, inherit (IOW, reference a copy of the passed in Object) the properties and methods of another object that is passed in.
var john = Object.create(Person);
In the above code, the john object is created and it's
prototype property points to a created object that has the methods and
properties of the Person object? Or to put it differently, Object.create makes a copy of the Person object and puts it in a memory space that the prototype property of john points to. Is this a correct understanding of what's going on?
If so, is the reason that a copy of the object ('person') is made, that the prototype of john points to, because that allows the values of the properties and methods to be modified without overwriting the props/methods in the Person object that the prototype object associated with john inherited?
I am trying to break this down so I can understand and trying not to over-complicate the concept.
Here is a picture I drew to further illustrate my current understanding:
No, there is no copying of anything involved. Just strike that part:
Prototype: A built in property that all objects have (except the Base Object) which points to and references a 'proto{}' object which is a copy of another object whose properties and methods can then be referenced if not found in the original object.
Keep it simple.
And yes, because there is a direct reference and nothing else involved, this means that any changes to the inherited properties of the prototype object will dynamically reflect in the object.
Related
I need some help for understanding the prototype chain. I don't understand / not quite sure if my assumptions are correct. I want to understand the link to the Object.prototype.
One example
function A(){};
var newObject=new A();
I know the newObject has an internal property [[prototype]] which has a reference to A.prototype.
And this prototype-Object has also an internal property with reference to Object.prototype, right?
But why does it have that reference? Is it because the prototype of A (used as constructor) is an object which can be imagined to be created by A.prototype=new Object() ( which will be done automatically in the background). And now I have a reference to the prototype of Object?
I hope I explained it clearly.
Please let me know your comments.
Many thanks
Yes, your understanding is correct.
In JS, pretty much all the objects have a reference to Object.prototype in their prototype chain.
The [[Prototype]] of an object refers to Object.prototype as the end of a prototype chain. In your example, this means what you described:
[[Prototype]] [[Prototype]]
newObject -----------------> A.prototype -----------------> Object.prototype
That applies to...
objects created by the Object constructor (i.e. new Object(...)),
those created with an object literal (which you can think of as syntax sugar for a new Object() call followed by a bunch of Object.defineProperty calls) and
objects created internally by the JS interpreter (like A.prototype which is created automatically when you define the A function).
There are also exceptions of this "rule" though:
Object.prototype itself.
If it had a reference to... well, itself, it would create and infinite recursion when a nonexistent property is looked up. Hence, it has no prototype, which means that its [[Prototype]] is null (that's how a prototype chain "ends").
Custom objects created using Object.create or modified with Object.setPrototype.
The [[Prototype]] can be set to anything this way, including null or other objects whose prototype chain doesn't end with Object.prototype.
This is indeed what the ECMAScript specification prescribes. When a function is defined with the function keyword, then an object is created from Object.prototype which is assigned to the function's prototype property, and therefor will be used as prototype for any object that is constructed by that function.
This specification can be found at Make Constructor, step 5.a:
5.a. Set prototype to OrdinaryObjectCreate(%Object.prototype%).
When it comes to javascript every value is either an object (arrays, objects, sets, maps...) or a primitive(Numbers, strings, bool ...) objects and primitives are the two data types in javascript a . You have the Number, String , Array and even Object constructors which you can use to create the corresponding value.
And when you create new object using the new operator the following steps happen consecutively:
// 1. New empty object is created
// 2. the constructor function is called, and the this keyword is assigned to the empty object i.e this = {}.
// 3. the empty object is linked to the prototype of the constructor functio i.e {}.proto = constructorFunction.prototype.
// 4. the constructor function automatically return the new object {}.
keep in mind that constructorFunction.prototype is the prototype of the new object that is created from the constructorFunction and not of itself.
I hope this clears things up a little for you!
But why does it have that reference?
To answer in one sentence - because prototype is an object itself and has its own prototype. When you create function in JavaScript it has a property called prototype. When you use that function as a constructor function (with new operator), new object is creating which as you wrote is linked to its constructor function prototype via internal [[prorotype]] property. That prototype object is plain JavaScript object which [[prototype]] property references Object.prototype.
I am trying to understand prototypes and dealing with some interference from my understanding of various other constructs.
Can someone explain to me what Object is in Javascript? To clarify, I know what an object(with a lower-case 'o') is, but not what Object (with a capital 'O') is. I understand that any object that is created in JS has a hidden prototype object attached to it. The prototype object is both a property of the parent object, and an object itself, with its own properties that can be accessed using the following command objectName.prototype; additionally, among the properties of the prototype object is a prototype object. Is Object the same as prototype object? If not, what is Object -- the global object? How does it/they relate to the window object or global object?
Thanks in advance for your help. I've scoured the internet for an answer on this, and couldn't find one that was both accessible or understandable. Although I'm not a 10-year old, if you would kindly explain it to me as though I am, I won't be offended, and will greatly appreciate the effort.
I understand that any object that is created in JS has a hidden prototype object attached to it.
Basically yes. Every object has an internal property, denoted as [[Prototype]] in the specification, whose value is simply (a reference to) another object. That other object is the first object's prototype.
A prototype object itself is not hidden though, and you can explicitly set the prototype of an object, via Object.create:
var foo = {x: 42};
var bar = Object.create(foo);
console.log(bar.x); // 42
console.log(Object.getPrototypeOf(bar) === foo); // true
In this example, foo is the prototype of bar.
The prototype object is both a property of the parent object, and an object itself
First of all, there isn't only one prototype object. Any object can act as a prototype and there are many different prototype objects. And when we say "prototype object", we are really referring to an object that has the "role" of a prototype, not to an object of a specific "type". There is no observable difference between an object that is a prototype and one that isn't.
I'm not quite sure what you mean by "property of the parent object" here. An object is a not property, at most it can be the value of a property. In that sense, yes, an object that is a prototype must be the value of the internal [[Prototype]] property of another object.
But that is not much different than every other relationship between two objects (so nothing special). In the following example bar is an object and also assign to a property of foo:
var bar = {};
var foo = {bar: bar};
Is Object the same as prototype object?
No.
Object is (constructor) function for creating objects. var obj = new Object(); is the same as var obj = {};. However, using object literals ({...}) is more convenient which is why you are not seeing new Object used that much.
For every constructor function C, the following holds true:
Object.getPrototypeOf(new C()) === C.prototype
i.e. the value of the C.prototype property becomes the prototype of new instance of C created via new C.
Object.prototype is actually the interesting part of Object and the most important one. You may have heard about the "prototype chain". Because a prototype is just an object, it has itself a prototype, which is an object, etc. This chain has to end somewhere. Object.prototype is the value that sits at the end of basically every prototype chain.
There are many prototype chains because every value that is not a primitive value (Boolean, Number, String, Null, Undefined, Symbol) is an object (which includes functions, regular expressions, arrays, dates, etc).
If not, what is Object -- the global object?
See above. It's not the global object, the global object in browsers is window, and while every JavaScript environment must have a global objects, at least so far there is no standard way in the language to reference it (edit: I guess this in the global environment would one cross-platform way).
How does it/they relate to the window object or global object?
The only relation really is:
Object is a property of the global object, and thus a global variable.
You may think the global object's prototype is also Object.prototype, but that is not necessarily the case
Reading material:
You Don't Know JS: this & Object Prototypes ; all of gettify's books in the series are pretty awesome.
http://felix-kling.de/jsbasics/ ; shameless plug for some very concise slides that I created for a JavaScript class that I'm teaching from time to time. Might not be detailed enough to be useful on it's own (and contains typos ;) )
If we create a object Function or Object, the creation process put reference of prototype prop of Object or Function object to the prototype of the new object! or copy all the props in the Obj or Func prototype prop to as the props of the new object?
If it reference the prototype of Obj Func to new obj prototype prop, so if we change one of them prop then it is like we change all of the object created until now and later, get affected!
If it copy, so it mean it copy a lot of functionality for each object? redundancy!
So confused and many other related question so lets go step by step, maybe also the question is not correct ones.
Thanks in advance, please if there is other such discussion refer me to that so don't waste time.
__proto__ VS. prototype in JavaScript
Confusion resolved based on these info
proto is different than prototype property.
only function has prototype.
proto in a object refer to a prototype of a function, most of the time the function that built that object.
The info in above link and diagram on it is the most you need to understand
MDN has a huge scary warning about modifying the prototype in your code:
Changing the [[Prototype]] of an object is, by the nature of how
modern JavaScript engines optimize property accesses, a very slow
operation, in every browser and JavaScript engine. The effects on
performance of altering inheritance are subtle and far-flung, and are
not limited to simply the time spent in the Object.setPrototypeOf(...) statement,
but may extend to any code that has access to any object whose
[[Prototype]] has been altered. If you care about performance you
should avoid setting the [[Prototype]] of an object. Instead, create a
new object with the desired [[Prototype]] using Object.create().
—MDN > JavaScript > Object.setPrototypeOf()
I’m wondering if there are any situations where you can modify an object’s prototype without causing cascading optimization effects that kill your program's performance. It seems like there should be. For example if you only modify the prototype right after the object is created (and before its used by anything else). But I imagine this is very engine-dependent.
So does anyone know if there are efficient ways to modify an object’s prototype?
Edit: The motivation for this question comes from a desire to create objects that actually inherit from Function. And the only way I know how to do that is by modifying the prototype of a function. See the very bottom of Raynos’s answer here: javascript class inherit from Function class
The motivation for this question comes from a desire to create objects that actually inherit from Function.
It seems what you are trying to do is the following:
Create new objects
Set these objects' prototype (or __proto__ property) to refer to Fuction.prototype such that they inherit properties from Function.prototype, e.g.:
.apply
.call
.bind
You should never need to change any object’s prototype as long as you can correctly set it to the desired reference at the time the object is created.
Answer One: How to Set an Object's Prototype
You can set any object’s prototype upon creation using Object.create(). Note that assigning any object's prototype to Function.prototype will not cause the object to be a callable function. But if you still wanted to assign the prototype to refer to Function.prototype, or to some other object, you could do the following:
var obj1 = Object.create(Function.prototype);
This will:
Create a new object, obj1
Set its prototype (or __proto__ property) to refer to Function.prototype or whatever object you pass in as the argument
i.e., it will delegate failed property lookups to Function.prototype via the prototype chain (this is what a JavaScript prototype is and what __proto__ refers to: a place to delegate failed property lookups)
This does not require you to use Object.setPrototypeOf() to change an existing object's prototype because it assigns the prototype at the moment the object is created. See MDN docs for Object.create() for more examples and info -- this does not carry the same scary warnings as setPrototypeOf(). You can use Object.create() to set any new object's prototype.
Answer Two: Functions are Already Objects
That said, if you want an object that behaves like a function, you can simply create a function. A function is still an object, but with additional function-specific properties and behaviors; you can still treat it like an object by assigning properties to it. If you're looking to create a function that also acts like an object, or an object that can also do the same things as a function, then a function already does that. You can do things like:
var func = function() { return 'hello world'; }; // func is a function
func.property1 = 'foo'; // func is also an object
func.property2 = 'bar';
The best solution to your question may be to take advantage of the fact that functions are, in fact, already objects with added function-abilities.
I want to have a clear understanding of the BOM structure.
Question 1: For example I have an html document and there are only one element <p id="1"> </p> iside <body></body>. When a browser analizes the html document it starts to build the DOM tree inside the BOM tree and my paragraph element is converted into a p object who is put in the determined place of the DOM tree - window.document.lastChild(I have got the html object).lastChile(I have got the html object).firstChild(I have got the p object).The question is where are the all objects of the p object prototype chain are situated - HTMLParagraphElement, HTMLElement, Element, Node? If I am taking the HTMLParagraphElement object (document.getElementById("1").__proto__;) and asking "Who is your parent?" ((document.getElementById("1").__proto__.parentNode;)) then some mistake appears Uncaught TypeError: Illegal invocation.
Question 2: there was a thought in my mind that all prototype objects (HTMLElement, Element, Node...) are laying in the root of the window object (because all programmer's objects and prototype objects are laying the root of the window object). I looked at this window root and saw that there are a lot of consctructor functions (which have the same names as prototype objects (function HTMLElement(), function Element(), function Node()...). Each of These functions has __proto__ property and constructor property at the same time. How is it possible that constructor functions have prototypes? A constructor function just is throwing properties (like this.propname) inside a new object. I thought that only "typical" object (var obj={name:1};) is able to contain a prototype property. For what this prototype is needed for a function?
Question 3: It turned out that a window object has some prototype object with the same name and the prototype chain goes on. Where are these prototype objects are laying in a window object? I thought that a window object is laying on the top of the objects hierarchy. As I see the more I know about the javascript the more I understand that I know nothing. Help me, please, to understand it.
First, almost no object has a __proto__ property. Don't rust the developer tools which display it as an own property. __proto__ is a not-much-standard accessor property defined in Object.prototype which provides access to the internal [[Prototype]] slot of an object.
All ordinary objects have an internal [[Prototype]] slot. It determines from which other object the former one inherits from.
For example, [] creates an array whose [[Prototype]] is Array.prototype, where methods like push and forEach are defined.
All constructors have a prototype property. When instantiated, the [[Prototype]] of the instance will point to the value of the prototype of the constructor at that moment.
Constructors are function objects, so it makes sense they inherit function methods. That is, their [[Prototype]] is usually Function.prototype or an object which inherits from it.
Some examples:
Object.getPrototypeOf([]); // Array.prototype
Object.getPrototypeOf(Array); // Function.prototype
Object.getPrototypeOf(Function); // Function.prototype
Object.getPrototypeOf(Object); // Function.prototype
Object.getPrototypeOf(Array.prototype); // Object.prototype
Object.getPrototypeOf(Function.prototype); // Object.prototype
Object.getPrototypeOf(Object.prototype); // null
The reason you got an "Illegal invocation" exception is because parentNode is defined in Node.prototype, from which all nodes inherit from (not necessarily directly). parentNode is defined as a getter which returns the parent of the node on which the property was accessed.
document.documentElement.parentNode; // document
document.documentElement.hasOwnProperty('parentNode'); // false
Node.prototype.hasOwnProperty('parentNode'); // true
Then, if you use Node.prototype.parentNode, if will attempt to retrieve the parent node of Node.prototype , but Node.prototype is not a node. Therefore, it throws. But you could use something like
Reflect.get(Node.prototype, 'parentNode', document.documentElement); // document
Finally, objects are not required to be stored somewhere in a tree rooted at the global object. Otherwise, they could not be garbage collected! Objects are just stored in memory, and they can be referenced by other objects or not.
(function() {
var obj = {}; // This object is not referenced anywhere
})();