__proto__ : function declaration versus object literal - javascript

I've just started reading this article and I'm stuck on the first paragraph:
For the code:
var foo = { x: 10, y: 20 };
we have the structure with two explicit own properties and one
implicit proto property, which is the reference to the prototype
of foo:
Figure 1. A basic object with a prototype.
My question...
Why does the diagram show a foo prototype for a basic object literal?
If I create two objects, it shows this isn't the case:-
object one - a function object / constructor function
object two - a basic object literal with key/value pairs like a dictionary
If I use the debugger, it shows that object one does indeed create a One.prototype which also has an Object.prototype further down the chain, but object two does not have a two.prototype, instead it goes straight to the Object.prototype.
Have i misunderstood the proto concept or is the article incorrect by implying object literals have their own prototype?
EDIT:
I've given up reading the article, it's broken English makes a complicated subject more complicated.
The guy in this video answers my question and to sum it up:
every object has a __ proto __
only functions have a prototype
prototype is the template used when using new operator

The __proto__ comes from the constructor's prototype.
In the first case, One is your constructor. You haven't assigned anything to One.prototype, so it defaults to a Object's __proto__ and you get the two levels of inheritance.
If you had added things to that object, they would show up as part of the One prototype.
function One() {
this.x = 4;
this.y = 'hhh';
}
One.prototype.z = 'foobar';
var one = new One();
In the second case, you are creating an object literal which has Object as it's prototype, so you only inherit from the Object prototype. Prototypes are objects themselves, so if you were to add properties to it, like so:
foo.__proto__.z = 'foobar';
You are modifying the instance of Object that is foo's prototype, it doesn't modify Object itself, only that particular instance of it. That is what the article means, by foo's prototype.
I just did a test in V8 and it seems an object literal doesn't have an instance of Object as it's prototype, it has Object's __proto__ itself, so you should not modify foo.__proto__, you would be modifying the underlying Object prototype that all Objects inherit from. If you do wish do modify it, you should create a new instance of Object first to add to:
foo.__proto__ = {};
foo.__proto__.z = 'foobar';
Example:
var x = {};
x.__proto__ = {};
x.__proto__.z = 'foobar';
var y = {};
y.z; // undefined
Object.z; // undefined
vs.
var x = {};
x.__proto__.z = 'foobar';
var y = {};
y.z; // 'foobar'
Object.z; // 'foobar'
In my opinion, it would be better if object literals automatically created a new instance of Object for their __proto__. Then again, there is no real reason in modifying the prototype of an object literal.
Also note that you should not use __proto__ directly, as it is deprecated, and its future replacement is strongly discouraged as well. You should use Object.create for implementing inheritance in Javascript.

There are two interrelated concepts with prototype in JavaScript:
First, there is a prototype property that every JavaScript function has (it is empty by default), and you attach properties and methods on this prototype property when you want to implement inheritance.Note that this prototype property is not enumerable: it is not accessible in a for/in loop. But Firefox, and most versions of Safari and Chrome, have a __ proto__ “pseudo” property (an alternative way) that allows you to access an object’s prototype property. You will likely never use this __ proto__ pseudo property, but know that it exists and it is simply a way to access an object’s prototype property in some browsers.
The prototype property is used primarily for inheritance: you add methods and properties on a function’s prototype property to make those methods and properties available to instances of that function.
The second concept with prototype in JavaScript is the prototype attribute. Think of the prototype attribute as a characteristic of the object; this characteristic tells us the object’s “parent”. In simple terms: An object’s prototype attribute points to the object’s “parent”—the object it inherited its properties from. The prototype attribute is normally referred to as the prototype object, and it is set automatically when you create a new object.To expound on this: Every object inherits properties from some other object, and it is this other object that is the object’s prototype attribute or “parent.” (You can think of the prototype attribute as the lineage or the parent). In the example code above, newObj‘s prototype is PrintStuff.prototype.

Related

Can an object have properties which its prototype doesn't have?

In JavaScript, must an object and its prototype (i.e. its property prototype as an object) have exactly the same set of properties?
Can an object have properties which its prototype doesn't have?
In JavaScript, must an object and its prototype (i.e. its property
prototype as an object) have exactly the same set of properties?
No. The prototype is used to create instances of objects. At the moment an instance is created, the instance becomes a separate object from the prototype and modifications to it don't affect the prototype (however, changes to the prototype will affect the instance). Welcome to prototypical inheritance!
Can an object have properties which its prototype doesn't have?
Yes, here's an example:
function foo(){
// doesn't matter what it does
}
let fooInstance = new foo();
console.log(foo.prototype.bar); // undefined
console.log(fooInstance.bar); // undefined
console.log("************************");
// Give the instance object a new property.
// This does not create a property on the instance's prototype
fooInstance.bar = "baz";
console.log(foo.prototype.bar); // undefined
console.log(fooInstance.bar); // baz
console.log("************************");
console.log(foo.prototype.hasOwnProperty("bar")); // false
console.log(fooInstance.hasOwnProperty("bar")); // true
I case you have to stick to the prototype you may seal() the object.
The Object.seal() method seals an object, preventing new properties from being added to it and marking all existing properties as non-configurable. Values of present properties can still be changed as long as they are writable.
Object.seal() MDN definition
You can also freeze() an Object, but this will prevent changing any part of the object.

JavaScript OOP concepts - Properties

On MDN they state the following:
Properties are variables contained in the class; every instance of the
object has those properties. Properties should be set in the prototype
property of the class (function) so that inheritance works correctly.
Looking at the sections I've set to bold I assumed this meant:
myClass.prototype.newProperty = ...
However their example shows the following:
function Person(firstName) {
this.firstName = firstName;
console.log('Person instantiated');
}
var person1 = new Person('Alice');
var person2 = new Person('Bob');
// Show the firstName properties of the objects
console.log('person1 is ' + person1.firstName); // logs "person1 is Alice"
console.log('person2 is ' + person2.firstName); // logs "person2 is Bob"
In their example they're adding the property 'firstName' directly to the class/function using 'this'.
Does this mean:
a) That the function declaration is the prototype? I.e. myClass is the prototype which also has a property prototype which by default is set to Object?
b) That using 'this.' in the function declaration does actually add the property to the myClass.prototype
Edit: Updated title
JavaScript doesn't have classes, stop thinking in classes, because that doesn't work with JavaScript (yes, even with the ES6 class syntax, it's just sugar, there aren't actual classes in JavaScript).
By adding the property to the object's prototype, you ensure that it and any other objects with the same prototype will share this property, this means that they'll all have it, but it also mean that if you change it on one, it will change with all of them. Oops.
The creation of a new object with the new keyword is fairly straightforward:
Create an empty object
Make that object prototype the same prototype as the constructor's
Call the constructor with this as the newly created object.
So adding a property to the prototype of an object will have it shared among all instances of the same constructor, while adding it to this in the constructor will have it only on this specific instance. Because it's set in the constructor, it's safe to assume that all instances will have that variable in them, although it won't be shared with all other instances.
When you call a JavaScript property, the engine will look for it in the following fasion:
Look for the property on the object itself (that's this inside of methods of that object)
If not found, look for the property on the object's prototype
If not found, go up the prototype chain and look for it there
So in your Person example, the lookup chain will look like:
this > Person.prototype > Object.prototype
The constructor's will look like this:
this > Person.prototype > Function.prototype > Object.prototype
Person is a function, so its prototype is inherited from Function.prototype, similarly any function is an Object.
So to your specific questions:
The function declaration is not the prototype. See the object creation process above.
No, this applies the property on this instance, while prototype is shared among all instances.

Object.create setting __proto__ but not prototype

I'm pretty new to using object.create instead of the classical js way to acheive prototypical inheritance.
In Chrome at least I was surprised to see the following code:
var baseObject = {
test : function(){
console.log('Child');
}
}
var newObject = Object.create(baseObject);
newObject.test = function(){
console.log('Parent');
this.__proto__.test();
}
console.log(newObject);
newObject.test();
Produces this (simulating the output in web tools):
Object {test: function, test: function}
test: function (){
__proto__: Object
test: function (){
__proto__: Object
Parent
Child
So you see it's not setting prototype but instead only "__proto__", which I thought was discouraged in its use. You can see that in my code I'm able to properly inherit, and call the parent object, but only using "__proto__". Using "prototype" results in an error (undefined).
What's going on here? I figured object.create would set the "prototype" instead as that is the standard (or so I had assumed). Why is it populating and making me using "__proto__"
No using __proto__ to set up your prototypal inheritance is discouraged because it's non-standard. That doesn't mean you can't use Object.create() to make a new object with a particular prototype object.
Objects do not have a .prototype property by default. You're confusing the .prototype object of a function.
So if I have a function like this:
function Foo() {
}
That Foo function object has a .prototype property that references an object that will be used as the __proto__ of any objects created when invoked as a constructor.
var f = new Foo();
So now f is an object with the Foo.prototype in its prototype chain. You can verify this using Object.getPrototypeOf();
Object.getPrototypeOf(f) === Foo.prototype; // true
What Object.create gives you is the ability to set up the same prototype chain, but without using a constructor function. So this would be equivalent.
var f2 = Object.create(Foo.prototype);
Now we have an object that is set up in the same manner as the original f object.
Object.getPrototypeOf(f2) === Foo.prototype; // true
Object.getPrototypeOf(f2) === Object.getPrototypeOf(f); // true
So it's just a different way of doing what is ultimately the same thing. The relationship between an object and its prototype chain is an internal relationship. The non-standard __proto__ just exposes that relationship.
An instance's __proto__ property should be the same as the constructor's prototype property.
When an object is created, its __proto__ property is set to reference the same object as its internal [[Prototype]] (i.e. its constructor's prototype object). Assigning a new value to __proto__ also changes the value of the internal [[Prototype]] property, except where the object is non–extensible.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/proto#Description
Object.create() sets the prototype for that particular object instance. prototype is a property on a constructor function that is the object automatically assigned as the [[Prototype]] for each instance created by using the new operator with that constructor function.
__proto__ is a non-standard way to access the [[Prototype]] for a particular instance. You can also call Object.getPrototypeOf(this) for a standard way to access the prototype.

Javascript prototype behavior

I have a method that will let me select the prototype object when creating a new object (copied from "Javascript: The Good Parts" book):
Object.create = function(o) {
var F = function() {};
F.prototype=o;
return new F();
}
Now say, I have an object:
var car = {
model: "Nissan"
};
And I create a new object based on this object, using the "Create" method:
var car1 = Object.create(car);
I can then add a property to car and it will dynamically get added to car1 (dynamic prototyping). So for eg:
car.year=2011; // Gets added to "car"...
alert(car1.year); // ... Is also avaialable to car1
Q1) This behavior indicates that "year" got added to car's prototype, which is why it is available to car1. Is this correct? If not, then where does "year" get added and why is it available to both "car" and "car1"?
Also, per the rule of delegation, if a method cannot be found on an object, it will search its prototype and then check all the prototypes up the chain till it gets to Object.prototype. So now, if I type something like this:
Object.prototype.originCountry = "Japan";
alert(car.originCountry); // Outputs Japan
alert(car1.originCountry); // Outputs Japan
So far so good; however, if I do:
Object.carColor= "White";
alert(car.carColor); // Error!
Q2) When I add a property to "car" (see car.year example above, it gets added to car's prototype. However, when I add a property to Object, it does not get added to Object's prototype? If it does get added to Object's prototype, then why is it not available to "car", per the rule of delegation?
Why is this happening?
When you do this:
Object.carColor = "White";
Then the property carColor does not get added to the Object's prototype. It is now a property of Object. To see what you expect, what you would do is:
Object.prototype.carColor = "White";
Then after that:
alert(({}).carColor); // Will alert "White"
So what happens here is that. any object created including {} (which is nothing but an empty object) is a new instance of Object and hence shares the properties of whatever is set in the prototype of Object.
As for how your Object.create function works. Let us look at it line-by-line:
1. var F = function() {};
You just create a new function, an essentially blank object. The reason you use a function and not something like {} is because a function can be coupled with a new call to create a new instance of that object wherein the function would act as a constructor.
2. F.prototype=o;
You set the prototype of the new blank function to the object you've created. Now, this is purely a reference. It is not a deep-copy. What I mean is that as the object o changes, so will any instances of the objects (actually they won't change, but they would 'seem to' change. More on that later).
3. return new F();
Now you just create a new instance of that function, which has a prototype as the object you passed.
When you do the following:
var car1 = Object.create(car);
You get an object car1 which has the prototype has car. So when you do this:
car.year = 2011
It isn't like car1 changes. It is more like the object that the prototype refers to changes. So when you do something like:
car1.year
A search is made (first in the prototype, then in the object) for a property called year and turns out, that the prototype has it and hence car1.year will return 2011.
So the bottom line is this:
A prototype is shared amongst instances.
Changing the properties of an Object will not manifest into any instances changing.
In your first example, you are adding to the prototype of your car1 because car === F.prototype and car1 instanceof F. So to Q1: yes.
Object is the constructor function of all objects, as F is to your car1. If you add something on Object.prototype, it will be available on all objects - that's the reason why you should not, such non-enumerable properties mess up all for-in-loops. If you set a property of the Object constructor function, nothing changes for the things that inherit from it. Don't forget: Object equals the F function, not the o parameter for prototype setting. new Object() is like Object.create(Object.prototype).
That function doesn't let you select the prototype object it creates a nmew object constructor, the object argument as prototype and then return a new object based on the constructor.
That new object will inherit methods and properties from the object arguments. This is to allow the creation of new objects that inherits from others.
The reason this works (and by the way Object is a core javascript object and should not be extended)
Object.prototype.originCountry = "Japan";
alert(car.originCountry); // Outputs Japan
alert(car1.originCountry);
and this doesn't
Object.carColor= "White";
is because the first extend the prototype object of Object, which means object build with the Object constructor will inherits those methods and properties.
When the later is what we call a static function which does not get passed to object created from the Object constructor.
I would recommend reading more about prototypal inheritance in Javascript. here is few links.
http://www.webreference.com/programming/javascript/prototypal_inheritance/index.html
http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=xEJ2PwtH2Oh
http://unscriptable.com/2007/04/17/inheritance-explained/

Confused about JavaScript prototypal inheritance

In the book "JavaScript the definitive guide 5 edition", section 9.2 Prototypes and Inheritance, I find the following words:
In the previous section, I showed that
the new operator creates a new, empty
object and then invokes a constructor
function as a method of that object.
This is not the complete story,
however. After creating the empty
object, new sets the prototype of that
object. The prototype of an object is
the value of the prototype property of
its constructor function. All
functions have a prototype property
that is automatically created and
initialized when the function is
defined. The initial value of the
prototype property is an object with a
single property. This property is
named constructor and refers back to
the constructor function with which
the prototype is associated. (You
may recall the constructor property
from Chapter 7 ; this is why every
object has a constructor property.)
Any properties you add to this
prototype object will appear to be
properties of objects initialized by
the constructor.
Now, if that is true, how could prototypal inheritance exists? I mean, let's say the prototype object of a constructor function has a constructor property initially. Because the prototype object itself is an object, to determine its constructor we often use prototype_object.constructor. But now the prototype_object already has a constructor property itself, and it points to the constructor function with which the prototype is associated. In this situation how can inheritance exists?
The .constructor property honestly doesn't matter very much, and has very little to do with inheriting from other objects in JavaScript. It's just a convenient handle to an object's constructor.
For example, if you have an instance of something, and you'd like to create another instance of that thing, but you don't have a direct handle on its constructor, you could do something like this:
const myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]
const car2 = new myCar.constructor();
console.log(car2.constructor); // [Function: Racecar]
It's important to understand that the .constructor property and the class of an object are not synonymous. As you may have already guessed, the .constructor property is dynamic, just like most other things in JavaScript, so it should not be used for anything like type checking.
It's also important to understand that the .constructor property does not mean that something is a subclass of something else. In fact, there is no reliable way to find out if something is a subclass of something else in JavaScript. Because it's a dynamic language, and because there are so many ways to inherit properties from other objects (including copying properties from other objects after instantiation), type-safe subclasses don't exist in JavaScript like they exist in other languages.
The best way to know if something is a compatible type is to feature-test properties. In other words, duck type.
The instanceof operator ignores the .constructor property. Instead, it checks whether or not the constructor's .prototype exists (with an identity check) in the prototype chain of the object.
With manual constructor functions, inheritance can confuse the .constructor property connection (making it refer to the wrong constructor). You can fix it by manually wiring up the connection. For example, the canonical way to do so in ES5 is this:
function Car () {}
console.log(Car.prototype.constructor); // Car
function Racecar () {}
Racecar.prototype = Object.create(Car.prototype);
// To preserve the same relationship we have with the Car
// constructor, we'll need to reassign the .prototype.constructor:
Racecar.prototype.constructor = Racecar;
var myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]
ES6 classes do this for you automatically:
// ES6
class Car {}
class Racecar extends Car {}
const myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]
That said, I'm not a big fan of either constructor functions or ES6 classes, and I generally have little use for the .constructor property. Why? Because factory functions are far more flexible, far more powerful, and they don't have the pitfalls related to constructor functions and class inheritance. See "Factory Functions vs Constructor Functions vs Classes".
Let say, Dog is a Mammal.
function Mammal() {
this.milk = true;
};
function Dog() {
this.bark = true;
}
Dog.prototype = new Mammal;
So prototype of Dog points to an object of Mammal. This Mammal object has a reference to its constructor so when Dog is new, JavaScript see that Dog prototype is a Mammal so Mammal's constructor is called to produce a valid Mammal object (another one) then make it a Dog object using Dog constructor.
From this, the constructor of Dog.prototype is a Mammal (a Mammal Object that has extra fields and functions added) BUT constructor of Dog is Dog. The inheritance exist because the an instance of Dog has a Mammal as a prototype; hence, Dog is a Mammal. When a method is called and JS cannot find it from Dog.prototype, JS look in Mammal.prototype (which is an Object that has extra fields and functions added).
Hope this helps.
Don't worry about the constructor property - it is irrelevant.
Skip those sentences and you might follow it better.
If you are still unsure of your understanding, google for __proto__ - the internal prototype reference on JS objects. It is even exposed to scripts on Firefox and Safari.
A good reference is https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/The_Employee_Example/Object_Properties/Inheriting_Properties
If you have an object obj, it's prototype is obj.prototype and constructor property referring to obj's constructor is obj.prototype.constructor.
For the object obj.prototype the situation is the same. Let's say proto = obj.prototype, then the reference to the constructor of proto would be found at proto.prototype.constructor.
This is the same as obj.prototype.prototype.constructor, so there is no conflict with obj.prototype.constructor.

Categories

Resources