How Do Objects Created?
Solution 1:
I saw your post yesterday, but I was a little busy at that time, now I'm free and I'd like to answer your question.
When the code new Foo()
is executed, the following things happen:
Function Foo() is called, as @slebetman mentioned, since the function is called with the
new
keyword then it is treated as a constructor, an empty object is created.The object is linked to the function's prototype,inheriting from
Foo.prototype
.this
bound to the newly created object.this.bar = true
executed.new Foo
is equivalent tonew Foo()
, i.e. if no argument list is specified, Foo is called without arguments.The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in the first step is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
Let's say bar is stored in Foo's prototype, that explains why obj2 has the property bar and why obj3 is created by Object, but what if I create a couple more obj2s, that would mean they share the same variable bar on Foo's prototype, and I think this is not the case.
You are right.
bar
is a property owned by obj1
and obj2
, for example:
console.log(obj1.hasOwnProperty("bar")); // true
But if you add a property like this:
Foo.prototype.bar2 = true;
console.log(obj1.hasOwnProperty("bar2")); // false
The value of bar2
is shared by all the Foo
instances, but bar
property isn't shared by Foo
instances, each Foo
instance could have its own bar
value.
Can somebody give a more reasonable explanation on why obj2 and obj3 are like this?
- What happened to obj2 ?
When you declare constructor Foo
, Foo.prototype.constructor
will automatically point to Foo
, console.log(Foo.prototype)
will show that, actually this is called circular reference, which should be detected when you traverse an object recursively. But in your case, Foo.prototype.constructor = 3
, fortunately, the process of new Foo()
expression doesn't involve Foo.prototype.constructor
property, so it will be done correctly, but the value of obj2.constructor
or Foo.prototype.constructor
is still 3
.
- What happened to obj3 ?
Bar.prototype = 3
, my theory is that, when new Bar()
executed, as in Step 2, the created object is supposed to linked to Bar.prototype
, but since the value of Bar.prototype
doesn't refer to an object, implicitly a default value was assigned, which is the Object.prototype.
console.log(Object.prototype === Object.getPrototypeOf(obj3)); // true
Due to object.prototype.constructor
's reference to the Object
, obj3.constructor
also refer to the Object
, but obj3
's de facto constructor is still Bar
, because of Step 1, which also can be proved by console.log(obj3.foo); // true
.
More information: How objects are created when the prototype of their constructor isn't an object?
Solution 2:
Your understanding is almost correct except for this:
- the object searches for a constructor function
No, the constructor function is this:
function Foo(){
this.bar = true;
}
And you're calling the constructor function directly without the object existing:
new Foo();
new Bar();
That's just a function call. It's a bit special because of the new
key word. So, to modify your understanding a bit I'm going to take your description and change it a bit:
- a function is called
- since the function is called with the
new
keyword then it is treated as a constructor - an empty object is created
- the object is linked to the function's prototype
- the object is returned by an implicit return this
Note, there is no need whatsoever for the object to search for the constructor when it is created within a call to the constructor itself. The call to the constructor is the first step, not the third.
Note that this is a very high-level description of how objects are constructed. There are several details like how this
is treated that is glossed over.
Solution 3:
For instance, I explicitly set Foo.prototype.constructor to something else for obj2, but obj2 still has the property bar. [..]
In your case constructor
is just a prototype property on Foo
. It is not the constructor for obj2
as you would call it. The constructor for obj2
is Foo
. By applying a property named as constructor
to the prototype, you are not changing the constructor!
[..] but Let's say bar is stored in Foo's prototype, that explains why obj2 has the property bar [..]
Contrary to your belief, bar
is not stored in Foo
's prototype. It is a property which exists on obj2
instance. It is an instance property not a prototype property. The prototype property in your case is constructor
.
Look at these examples for more clarity:
function Foo() {
this.bar = true;
}
var obj = new Foo();
console.log('The instance property "bar" is ' + obj.bar);
Foo.prototype.baz = 4;
console.log('The prototype property "baz" is ' + obj.baz);
Foo.prototype.bar = 5;
console.log('The prototype property "bar"=' + Foo.prototype.bar + ' is overridden by instance property "bar"=' + obj.bar);
Post a Comment for "How Do Objects Created?"