understanding Prototype in javascript [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does JavaScript .prototype work?
Coming from Java background, I'm trying to understand javascript.
Please let me know if these are right.
Like in java, there is a supreme Object, from which all other objects inherit.
The prototype property is like a pointer that points to the parent object (classes in java)
For "Object" object, the prototype is null.
prototype property's values are strings denoting the objects nomenclature and aren't pointers like in C. The pointer concept is implemented using the hidden attribute,[[PROTOTYPE]] that is not accessible in script.
I'm using node.js instead of browser to learn JS.
I tried,
var human = Object.create(null); // same as var human;
console.log(Object.getPrototypeOf(human)); //null
var man = Object.create(human);
console.log(Object.getPrototypeOf(man));
//{}
//expected 'human'
var person = Object.create(Object.prototype); // same as var person = {}
console.log(Object.getPrototypeOf(person));
//{}
//expected 'object'

Yes, with the exception of Object.create(null) which doesn't inherit from anything.
Not sure what "parent object" is, but the prototype of a function consists of functions that are accessible by instances. Because Object.prototype.toString exists, so does {}.toString - it is inherited.
Yes, the prototype chain ends here.
No, .prototype (or the value returned by Object.getPrototypeOf) is an object which you can extend with properties, so that those properties are inherited by instances.
Your examples:
var human = Object.create(null); // same as var human;
No, it creates an empty object that doesn't inherit from anything. var human; sets human to undefined - which is not an object but a primitive value (not everything is an object in JavaScript).
var man = Object.create(human);
console.log(Object.getPrototypeOf(man));
//{}
//expected 'human'
Object.getPrototypeOf(man) returns the object human. This is an empty object; node shows it as {}. It is not a string. In fact, objects can be assigned to multiple variables. An object does not have a variable bound to it, so by design it is not possible at all to get a string. To check equality, you could do Object.getPrototypeOf(man) === human which yields true.
var person = Object.create(Object.prototype); // same as var person = {}
console.log(Object.getPrototypeOf(person));
//{}
//expected 'object'
This is indeed the same as {} - an empty object that inherits directly from Object. As said above, the prototype is Object.prototype and not a string. It looks empty but that's because Object.prototype's functions are available by default and hidden.

First, you need to read about the create method before you attempt to use it.
Second, invoke objects in the following manner:
var human = {}, man = {}, person = {};
Third, this is not Java. In Java classes and an understanding of classes are pretty important. Prototypes are completely optional in JavaScript. The only performance benefit offered by prototypes comes when you code makes heavy reuse of functions by reference in different scopes. If this style of coding does not apply to you then you likely do not need to use prototypes.
Prototypes are inherited from the parent, or some ancestor, object. A JavaScript parser will first look for local assignments and if none exist will then examine the current object's prototype for the presence of the named reference. In a nutshell this all you need to know at this early point in writing JavaScript.

Firstly, IMO, don't start off with node. Node is going to drag you into a pool of quicksand if you don't know javascript yet. Secondly, when I started off with function based code, then OO and only then I moved to prototypes. But if you really want to know, this question has already been answered over here. Feel free to ask me if you have any more questions!

Related

Where are built-in method in javascript?

please help me get it straight, I see every object in javascript leads to object Object in prototype chain and then to null, in console.log we can see properties and methods of objects but never its implementation, i wonder if this Object is a top-level object where all built-in are stored, is that so?
thank you all for answers!
Javascript is an object-based language. Which means that "everything" inherits from an Object, except Object itself, the top of the prototype chain is null. When you declare an array, you can use .lenght because that is defined in the prototype attribute. There are some exceptions, such as int, floats, etc.
In fact, when you run a console, you can see every method from its parents. Try creating a Constructor for a new object, let's say, for example:
var Person = function(name, yearOfBirth, job) {
this.name = name;
this.yearOfBirth = yearOfBirth;
this.job = job;
}
Add a method to this Person's prototype:
Person.prototype.calculateAge = function() {
console.log(2016 - this.yearOfBirth);
};
And create an instance of this new "class":
var sarah = new Person('Sarah', 1994, 'programmer');
Now go to the console on your browser and type sarah to see it's methods and variables. You'll notice that variables that are exclusive for John will appear on the first drop-down, but you'll also notice that John does not have calculateAge attached directly to it. That's because it's in its prototype, search for something called _proto_ and you'll see this method and also a construct and guess what else? Another _proto_, this time, it's the proto from Person's parent, or, in other words, the Object.
There you can find most of the methods from the Object itself.
Prototypes are what makes inheritance possible in javascript
Perhaps you want to look at ECMA specifications?
http://www.ecma-international.org/publications/standards/Ecma-262.htm
Each browser may have its own implementation of Javascript. Maybe something like this repo will help.
https://github.com/v8/v8

How to differentiate object created using {} vs object created using new keyword

There are 2 ways to create object
Direct
var x={};
Using the new keyword i.e using constructor function.
var x=new Object();
//or
var x=new Date(); //using constructor function.
Is there any way to determine how that object is created?
Fundamentally, in JavaScript, we don't care how an object was created. We normally just assume that if the object walks like a duck and talks like a duck, it's a duck. (This is called "duck typing.") And that turns out to be just as well, because we can't know how an object was created.
There are really two questions here:
How can you tell whether an object was created with an object initializer ({}) or new Object, and
How can you tell whether an object was created with one of those or some other constructor function (like Date).
The answer to Question 1 is: You can't. There is no difference, at all, in the resulting object, so you can't tell how it was created.
The answer to Question 2 is more complicated:
You can't know, for certain, that an object was created with a given constructor. JavaScript is too powerful, giving you too much control over the object, for it to be possible to be sure.
All you can know is what the object's prototype chain tells you, from which you can infer how it was constructed, but the inference could be incorrect.
Let's take your
var x = new Date();
example. To do that inference, you can use at least three tools:
instanceof: E.g., if (x instanceof Date). instanceof is an operator accepting an object and a function. It checks the object's prototype chain to see if the object the function's prototype property refers to is anywhere in the chain. If so, instanceof's result is true; if not, it's false. So if the object is created with new Date (or new Foo if Foo derives from Date), x instanceof Date will be true.
But again, JavaScript is really powerful, and you can fool it. For instance:
var x = Object.create(Date.prototype);
console.log(x instanceof Date); // true
We didn't use new Date to create that object, but we can't tell that we didn't. (And in this particular case, x won't work correctly as a Date, because Date objects have a special internal slot that normal objects don't have. Many of the Date.prototype functions will fail on the above. But that's Date-specific.)
The constructor property. By default, the prototype property on a function has a property, constructor, that points back to the function. E.g., Date.prototype.constructor === Date is true in the normal case. Since objects created with a constructor get that object as their prototype, you can use constructor to see what constructor (if any) is associated with that object: if (x.constructor === Date) will be true for something created with new Date (in the normal case).
But again, we can fool that check:
var x = Object.create({constructor: Date});
console.log(x.constructor === Date); // true
getPrototypeOf and related: You can check the prototype chain of an object directly (rather than just through instanceof). But this has the same vulnerability that instanceof has: We can fool it by creating the object with Object.create (or before Object.create was in the language, using custom constructor function).
instanceof has the advantage that it checks the entire hierarchy, and doesn't rely on constructor; in hierarchies created with ES5 and earlier (e.g., before ES2015's class), people frequently failed to set constructorcorrectly.
So again, fundamentally, we don't care how an object was created; and that's just as well, because we can't know, for sure, how it was created.
You can't differentiate creation of plain object since for javascript this is exactly the same thing.
var o1 = {};
var o2 = new Object();

Use cases of Object.create(null)?

If you create a regular javascript object using say var obj = {}; it will have the object prototype. Same goes for objects created using var obj = new MyClass(); Before Object.create was introduced there was no way around this. However nowadays it's possible to create an object with no prototype (respectively null as its prototype) using var obj = Object.create(null);.
Why is this important? What advantages does it bring? Are there any real world use cases?
It's a completely empty object (nothing inherited from any .prototype including Object.prototype), so you can be guaranteed that any property lookup will only succeed if the property was explicitly added to the object.
For example, if you want to store some data where you won't know the keys in advance, there's a possibility that a provided key will have the same name as a member of Object.prototype, and cause a bug.
In those cases, you need to do an explicit .hasOwnProperty() check to rule out unexpected inherited values. But if there's nothing inherited, your testing can be simplified to a if (key in my_object) { test, or perhaps a simple truthy test if (my_object[key]) { if appropriate.
Also, with no prototype chain, I would imagine that lookups of properties that turn out to not exist would be faster, since only the immediate object would need to be checked. Whether or not this pans out in reality (due to optimizations) would be determined with performance testing.
The only difference here between creating an object with {} and Object.create(null) is that the Object prototype will not be inherited from.
This means that any of the methods we typically assume we can call on any object will not exist, such as toString and valueOf. A list of these can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
From a performance perspective, creating an object simply by {} is actually much faster, so unless you specifically cannot have the functions under the Object prototype you should not create objects in that manner.
http://jsperf.com/null-vs-empty-object-performance

Is there a way to make 'constructor' a valid key in a JS object?

I'm currently making a chat AI that uses markov chains. One of the backend objects is an object that maps a string to any chain that it is a part of, such that:
var words = {}
words['test'] = [ ['this','is','a','test'], ['this','too','tests','things'] ]
Now, I have a problem. 'constructor' is a perfectly valid word, but it appears as though you can't map it as I have described above, as 'constructor' is a property of every object in JS (along with other things, of course). So to my question: is there a way to construct this map?
constructor isn't a property of every object. Though by default every object created from literal syntax will have constructor in its prototype chain. This is because those objects inherit from Object.prototype, which does have that property.
One solution is to use objects that have no prototype chain.
var words = Object.create(null);
words['test'] = [ ['this','is','a','test'], ['this','too','tests','things'] ];
Now there will be no inherited properties to confuse things. This won't work in IE8 and lower though.
Another solution is to use .hasOwnProperty() to see if the constructor property is on the object itself or inherited. If inherited, then it's not the one you want.
if (words.hasOwnProperty("constructor"))
console.log(words.constructor);
If the condition passes, then we know we're not using the inherited property, but rather the object's own property.

Is instantiating a object really just inheritance in some way in javascript?

I was reading a JavaScript book and as I was reading a chapter about inheritance, I wondered if every time you create a instance of a object is it really inheritance that happens, especially since they are similar.
Examples: Prototype Chaining - someObject.prototype = new someOtherObject();
Instantiating an object var myArray = new Array()
Similar right?
Additionally the book(JavaScript for web developers, By:Nicholas Zakas) stated, a link exists between an instance and a constructor's prototype.(The link is usually known as __proto__)
So can one argue that instantiating a object is like inheritance?
No. You are confused because one of the methods of accomplishing inheritance (viz. prototypal inheritance) takes, as the prototype, a given object. And one method of acquiring objects is via constructors.
In other words, there is nothing special about someObject.prototype = new SomeOtherObject(). You could just as well do
someObject.prototype = { myObjectLiteral: "isJustAsGoodAsYourConstructoredInstance" };
or even someObject.prototype = false. The two operations, very literally, have nothing to do with each other.
EDIT To address the quote OP found in his book:
"Recall the relationship between
constructors, prototypes, and
instances: each constructor has a
prototype object that points back to
the constructor, and instances have an
internal pointer to the prototype."
Unfortunately, this is misleading at best, and plain wrong at worst. Consider what "each constructor has a prototype object that points back to the constructor" would mean. It would mean that, for example,
Array.prototype === Array
Function.prototype === Function
function CustomConstructor() { }
CustomConstructor.prototype === CustomConstructor
But all of these statements output false if you type them in your console.
Now consider "instances have an internal pointer to the prototype." This is true, but does not fit with the terminology he is using. What this means is:
var myProto = {};
function CustomConstructor() { }
CustomConstructor.prototype = myProto; // inherit from the myProto object.
var x = new CustomConstructor(); // x is an "instance"
Object.getPrototypeOf(x) === myProto; // Object.getPrototypeOf fetches the "internal pointer"
But as you can see, I didn't inherit using a constructor, as I tried to point out above. Instantiating an object is not inheritance in any way. It is simply that the prototype property of constructors is how prototypal inheritance is accomplished, just like classical inheritance is accomplished by placing extends BaseClass after a class definition in Java. In turn, this difference is present because prototypal inheritance lets you inherit a prototype object instance, not a base class.
The JavaScript Garden has a few good sections that might help if you want more information. Relevant are "The Prototype," "Constructors," and "The instanceof Operator."
Without using objectType.inherits() if I got your concept of inheritance then it is if you take just the right part:
new someOtherObject()
This is instantiation of someOtherObject.
What happens here is you are creating an object of type someOtherObject that inherits structure from an empty object (provided you have not set a prototype on this). Because the default value of prototype is an empty object {}.
You are putting this object as prototype of someObject:
someObject.prototype = new someOtherObject();
Now if you create an instance of someObject this will happen:
You create someObject that inherits the structure of someOtherObject in that point in time, which inherits the structure of (empty)object when it has been instanced.
Maybe a better explanation is saying that the instance gets extended with the structure of its prototype at that point in time, and leave all of the inheriting wording aside, since just using that can mislead. Since classic inheritance uses base classes (types) and proto uses instances of those. Now it all depends on how you look at inheritance, which to argue about does not exists at all in javascript (object types are mutable at runtime) as by Karl Marx argues that real communism is not possible at all in the concept. If you agree with this last statement then comparing and asking about it does not matter, because neithercase is.

Categories

Resources