javascript two variables with same name co-exist in same object? - javascript

I'm trying my best to understand javascript. Here is a simple experiment in Chrome console which gets me very confused:
var foo=function(){this.p=1;}
foo.prototype.p=2;
var bar=new foo();
//foo{p:1,p:2} <- this is the output of Chrome console, from the last command above
The output of Chrome is what confuses me. It seems like bar is an object with 2 parameters, p:1 and p:2. Does this mean bar has 2 p??? What is the reasoning behind this?

Chrome DevTools console's inline (non-extended) object representation currently does not display any difference between own properties and inherited prototype properties.
Now let's break what's going on into smaller steps.
new foo() creates a new object whose internal proto property points to foo.prototype. This means this object can access all properties defined in foo.prototype. It's called prototype chain.
Now when you set a property of the same name in the object, it "shadows" the prototype's property by the same name, turning the latter inaccessible through regular property access (see #loxxy's answer using Object.getPrototypeOf(obj) to access the shadowed prototype property).
Once you add a function to the object or its prototype, the console allows you to display the extended object representation, which does differ own properties from prototype properties. In the next example I've added a q method to the prototype to allow this behavior. The properties inherited from the prototype are shown inside the object's proto internal property:
If you just want to have the number of instanced objects in the constructor's prototype, you can use:
var foo = function() {
Object.getPrototypeOf(this).p++;
}
foo.prototype.p = 0;
console.log(new foo()); //{p: 1}
console.log(new foo()); //{p: 2}
Or without the ES5 dependency:
var foo = function() {
foo.prototype.p++;
}
foo.prototype.p = 0;
console.log(new foo()); //{p: 1}
console.log(new foo()); //{p: 2}

Yes. Sort of.
bar has both:
A p property of its own.
bar.hasOwnProperty('p'); // true
bar.p; // 1
A p property still remaining on the prototype that it has through inheritance.
Object.getPrototypeOf(bar).p; // 2
Though, only 1 of them is accessible directly from bar at a time, with preference to the own property.
bar.p; // 1
delete bar.p;
bar.p; // 2
And, Chrome is showing both because it's traversing the prototype chain and looking for any enumerable properties.

The bar object has only one p with value 1
The earlier p with value 2 can be viewed in a readonly object which you can access with getPrototypeOf:
Object.getPrototypeOf(bar).p
You see both because the developer toolbar is designed to print an XML representation of the specified object which should intuitively show all the properties, whether directly accessible or not.

var foo=function(){this.p=1;} is constructor and executes after var bar=new foo();. So at the beginning p=2 and then p becomes 1. So:
var foo=function(){
// here this.p is equal to 2
this.p=1;
// here this.p is equal to 1
}
foo.prototype.p=2;
var bar=new foo();
EDIT:
JSON.stringify(bar);

When you acces a property, the javascript engine will seek it on the object instance, then on all its prototype chain.
So the meaning of p as a prototype property is to have a default value for p, wether you define it on any instance of the class or not. One example might be the number of wheel for a vehicle, that could default to 4, for instance.
If later you write to this property :
function Vehicle() {};
Vehicle.protoype.wheelCount = 4;
var myBike = new Vehicle();
myBike.wheelCount = 2 ; // this is a bike.
You won't change the value set on the prototype, but rather you'll create a new property on the instance, having the new value, so for instance :
var myCar = new Vehicle();
myCar.wheelCount // === 4
Now the very scenario you mention -setting a default value, and setting also an instance value in the constructor - doesn't make much sense, since you will have to use Object.getPrototypeOf to get to reach the default value. This is just a possibility that is of no use, just like there are many in all languages.

Related

How can I prevent javascript assignment from creating ownProperty

Here is an example:
var cat1 = Object.create({
name: "mia"
});
cat1.hasOwnProperty('name') // false
cat1.name = "haha";
cat1.hasOwnProperty('name') // true
This is rather surprising to me.
1) What is the design intention here?
2) How can I use = without create new properties?
What is the design intention here?
I didn't design JavaScript, but my guess would be to restrict the "scope" of mutations. Imagine you had two objects:
var proto = {name: "mia"};
var cat1 = Object.create(proto);
var cat2 = Object.create(proto);
If assignment to cat1.name would not create a new property, but update the prototype property instead, then cat2.name would suddenly be updated as well.
In other words, if assignment was updating prototype properties instead of the object's own properties, other objects could be affected by the change, without you even knowing it.
How can I use = without create new properties?
You cannot. You could assign to the prototype explicitly, but that requires you to know that the property is defined on the prototype:
Object.getPrototypeOf(cat1).name = 'haha';
hasOwnProperty shows properties defined on the object. At the same time:
Object.create({
name: "mia"
});
Creates new object with prototype {name: "mia"}. This means that property name will be defined for prototype not for object. Using prototypes makes some sort of optimization. Different object share the same logic from the prototype. Also the methods are not duplicated, so less memory is used.
When you defines own property by = you are showdowing the property with the same name from the prototype, so as #Felix Kling indicated you are not changing property in the prototype and other objects that use the same prototype will not be affected. You also can use Object.defineProperty(obj, prop, descriptor) instead of = in order to define own property of the object, but you can not use = on object without defining new properties you can do that on the prototype directly like this:
cat1.__proto__.name="other name" //avoid, this is not the best practive at all
By design, When you create object from a prototype, the new objects will share the properties with prototype object until you assign value explicitly to that property on that object, once its assigned since then the object will maintain its own state. below is sample code for the same.
var x = {"name":"mia"};
var o1= Object.create(x);
var o2= Object.create(x);
console.log(x.name,o1.name,o2.name); //output: mia,mia,mia
x.name="xxx";
console.log(x.name,o1.name,o2.name); //output: xxx,xxx,xxx
o1.name="yyy";
console.log(x.name,o1.name,o2.name); //output: xxx,yyy,xxx

Infinite prototypal inheritance in Javascript

I'm learning prototypal inheritance in Javascript, and for my understanding I'm trying to use it to send the process into infinite recursive chaining.
My idea of prototypal inheritance is that an object (which is a function) holds prototype link. Any instance of that object points to it. So if I say instance.someproperty it looks into the prototype chain of the parent object.
Assuming this, If I just point function prototype list to itself, it should go into infinite loop when object tries to access some property.
var p = function(){};
p.prototype = p;
// I also tried p.prototype = new p();
var q = new p();
// and now when I say q.something, it should never be able to find it.
I want to know why this doesn't work and how can I make it to go into infinite loop.
Using more common style:
function P(){};
P.prototype = P;
In ECMA-262, the internal prototype property is denoted by [[Prototype]].
Assigning a different object to P.prototype does not modify P's [[Prototype]], so its inheritance chain remains as:
P : P[[Prototype]] -> Function.prototype -> Object.prototype -> null
Given that P and P.prototype both point to the same object, the [[prototype]] chain of an instance of P is:
p : p[[Prototype]] -> P : P[[Prototype]] -> Function.prototype -> Object.prototype -> null
so no endless loop.
Without the assignment to P.prototype, p's prototype chain would have been:
p : p[[Prototype]] -> P.prototype -> Object.prototype -> null
To get an endless loop, you can assign an object to its own __proto__ property (the public way to access [[Prototype]]) in those browsers that support it, but I'm not sure that's a good idea, Firefox throws:
"TypeError: cyclic __proto__ value".
Well, to your first question:
var p = function(){};
p.prototype = p;
// I also tried p.prototype = new p();
var q = new p();
In the first one, all you're doing when you create an instance of p is setting the prototype to the function p itself, which is an object in its own right (with properties such as length, prototype, etc.). Its actual internal prototype is Function.prototype, which in turn has a prototype of Object.prototype.
The second one is slightly different -- close, but no cigar. When you're assigning new p() to p.prototype, the prototype property has not been set yet, so you're just going to get the original value of the prototype property as the instance's internal prototype.
Moving on to your second question. I don't actually see why you'd do this, as every property would be shadowed by its own instance property.
Even if you were allowed to (no browsers do), there would be no point.
Consider this:
var a = { b: 1 };
a.__proto__ = a;
Let's assume that this works, ignore the fact that this throws a TypeError in all browsers (which is specified for browsers in Annex B of the upcoming ES6 spec).
If you were to access the property b, you'd never go up the prototype chain.
If you attempted to access a non-existent property, an implementation (if it allowed for such a thing) could either go up the prototype chain, back to itself recursively, or recognise that the property would never be found and return undefined.
Of course, there is the situation where there are multiple objects involved:
var a = { x: 1 };
var b = { y: 2 };
b.__proto__ = a;
a.__proto__ = b;
However, this is ridiculously stupid and of no practical use (if permitted in the first place -- it isn't).

The assignment operator does not change properties in prototypes [duplicate]

var foo = {x: 1}
var bar = {__proto__: foo} // __proto__ specific to implementation
var bar = Object.create(foo) // same result as above with standard API
console.log(bar.x) // 1
foo.x = 2
console.log(bar.x) // 2
bar.x = 3
console.log(foo.x) // 2
Why did updating the inherited property x by the child object bar take no effect on the parent object foo but the opposite do?
#EDIT
After its creation the child own property remains unaffected when the parent object updates the shadowed property now.
foo.x = 4
console.log(bar.x) // 3
Assigning to an object property creates or updates the object's own property, there is no search on the prototype chain for an inherited property.
See ECMAScript Simple Assignment ( = ) §11.13.1.
It's all about prototypes. bar object has no x property, so when you try to access it, prototypes chain will be involved, and you will get value of foo.x. Then you update foo.x, and while accessing bar.x you will see another value also.
But when you set bar.x, x property will be created in bar object. foo.x is another one so it will stay the same.
And you should avoid using __proto__ in your code. It's browser specific feature (that's why it has underscores in name).

Does a new object in Javascript have a prototype property?

This is a purely trivial question for academic value:
If I create a new object, either by doing:
var o = { x:5, y:6 };
or
var o = Object.create({ x:5, y:6 });
when I query the o.prototype property, I get undefined. I thought that any newly created object automatically inherits the Object.prototype prototype.
Furthermore, invoking toString(), (a method of Object.prototype) on this object works just fine, implying that o does inherit from Object.prototype. So why do I get undefined?
There is a difference between instances and their constructors.
When creating an object like {a: 1}, you're creating an instance of the Object constructor. Object.prototype is indeed available, and all functions inside that prototype are available:
var o = {a: 1};
o.hasOwnProperty === Object.prototype.hasOwnProperty; // true
But Object.create does something different. It creates an instance (an object), but inserts an additional prototype chain:
var o = {a: 1};
var p = Object.create(o);
The chain will be:
Object.prototype - o - p
This means that:
p.hasOwnProperty === Object.prototype.hasOwnProperty; // true
p.a === o.a; // true
To get the prototype "under" an instance, you can use Object.getPrototypeOf:
var o = {a: 1};
var p = Object.create(o);
Object.getPrototypeOf(p) === o; // true
Object.getPrototypeOf(o) === Object.prototype; // true
(Previously, you could access an instance's prototype with o.__proto__, but this has been deprecated.)
Note that you could also access the prototype as follows:
o.constructor === Object; // true
So:
o.constructor.prototype === Object.prototype // true
o.constructor.prototype === Object.getPrototypeOf(o); // true
This fails for Object.create-created objects because they do not have a constructor (or rather, their constructor is Object and not what you passed to Object.create because the constructor function is absent).
Not a direct answer, but knowledge that everybody, who deal with inheritance in Javascript, should have.
Prototype inheritance in Javascript is a tricky concept. Up until now, it has been impossible to create an empty object (by empty I mean lacking even properties form Object via prototype). So this means that creating a new object always had a link to the original Object prototype. However, according to the specification, the prototype chain of an object instance isn't visible, but some vendors have decided to implement their own proprietary object properties so that you could follow it, but it's highly recommended not to use it in production code.
The following sample code demonstrates just two ways of creating an object instance.
var someObject = {};
var otherObject = new Object();
var thirdObject = Object.create({});
Even though you don't manually add object properties to empty curly braces, you still get automatically added prototype chain. The same goes for the second example. To visualize it better, you can type those lines into Chrome console and then enter either someObject, otherObject or thirdObject to see details. Chrome shows the prototype chain by adding a proprietary property __proto__ which you can expand to see what is inherited and where it's from. If you executed something like
Object.prototype.sayHello = function() {
alert('hello');
};
you would be able to call it on all instances, by executing otherObject.sayHello().
However, using something that was implemented quite recently (therefore not supported by all browsers), you can actually create a truly empty object instance (doesn't inherit even from Object itself).
var emptyObject = Object.create(null);
When you enter it into Chrome console and then expand the emptyObject to see it's prototype chain, you can see that it doesn't exist. So even if you implemented the sayHello function to Object prototype, it would be impossible to call emptyObject.sayHello() since emptyObject does not inherit from Object prototype.
Hope it helps a bit with the general idea.
JavaScript has two types of objects: function object and non-function object. Conceptually, all objects have a prototype (NOT A PROTOTYPE PROPERTY). Internally, JavaScript names an object's prototype as [[Prototype]].
There are two approaches to get any object (including non-function object)'s [[prototype]]: the Object.getPrototypeOf() method and the __proto__ property. The __proto__ property is supported by many browsers and Node.js. It is to be standardized in ECMAScript 6.
Only a function (a callable) object has the prototype property. This prototype property is a regular property that has no direct relationship with the function's own [[prototype]]. When used as a constructor ( after the new operator), the function's prototype property will be assigned to the [[Prototype]] of a newly created object. In a non-function object, the prototype property is undefined . For example,
var objectOne = {x: 5}, objectTwo = Object.create({y: 6});
Both objectOne and objectTwo are non-function objects therefore they don't have a prototype property.

two ways of creating object in javascript

I'm creating javascript object by doing something like:
function field(name,label){
this.name = name
this.label= label;
}
var a = new field("market","Mkt").
Then I assign a to another object.
object.newField = a;
The second way of doing it is to create a new property directly
object.2ndNewField = {
name: "market2",
label:"Mkt2"
}
I try to read the objects in other functions. They behave differently, however, when i stringify the object, it looks ok. What's the difference between the two properties i created?
btw is there any difference of the following object?
object.2ndNewField = {
"name": "market2",
"label":"Mkt2
}
The difference is that in the first case, the created object inherits from field.prototype then Object.prototype (i.e. its internal [[Prototype]] is field.prototype, whose internal [[Prototype]] is Object.prototype), where as in the second case it inherits only from Object.prototype.
Another way to look at it is:
object.newField instanceof field; // true
object.newField instanceof Object; // true
object.newField2 instanceof field; // false
object.newField2 instanceof Object; // true
or the inheritance chains are:
object.newField -> field.prototype -> Object.prototype -> null
object.newField2 -> Object.prototype -> null
where '->' means "inherits from".
For the First option...Stay away from using "new". You can badly effect your global namespace if "new" is used wrong, or omitted when it should be used. Plus you have to be careful with the use of "this" in some places within your code, as it could be bound to something that you don't think it is, or even to your global data.
In your 2nd option you gave, you can safely use it for objects that are only used as a collection of data/methods (i.e. not "class-like" behavior) . If you want something that you can create multiple instances of with private and public variables/methods and can be inherited from, then you should use a function that returns an object.
I did a pretty big write up and example here of how to safely create base objects and use inheritance. If you follow the link, you will see why I didn't retype it all on this post ;).
Hope this helps...

Categories

Resources