Reputation: 81
I've read the topic about "new" keyword in javascript (What is the 'new' keyword in JavaScript?). But, i'm still in the fog; let's talk about this example :
var foo = function() {
return {
setA: function(a) {
this.a = a;
},
readA: function() {
console.log(this.a);
}
};
};
And now what's about these two pieces of code :
One:
var bob1 = foo();
bob1.setA(10);
bob1.readA();
Two:
var bob2 = new foo();
bob2.setA(10);
bob2.readA();
I cannot see any differences at my level. So what is the gain to use the keyword "new" ?
Upvotes: 8
Views: 162
Reputation: 115940
If the constructor function foo
returns an object, then new foo()
is identical to calling the function foo()
directly. We can prove this is so by examining the ECMAScript behavior for new
:
Return the result of calling the [[Construct]] internal method on constructor [i.e., the constructor function]...
The [[Construct]]
internal method of a function is a special wrapper for calling the function's [[Call]]
internal method (which is just the function's normal behavior). Let's see the end of [[Construct]]
to see how this wrapper behaves:
8) Let result be the result of calling the [[Call]] internal property of F [the function invoked by
new
], providing obj as thethis
value and providing the argument list passed into [[Construct]] as args.9) If Type(result) is Object then return result.
10) Return obj.
In your case, your constructor function foo
returns an object, so step 9 of [[Construct]]
(and therefore, in turn, new foo()
) returns that object. But we see in step 10 that [[Construct]]
could return some other value called obj, which is equal to the this
value inside the constructor. Let's rewind and see what that's all about:
1) Let obj be a newly created native ECMAScript object.
...
4) Let proto be the value of calling the [[Get]] internal property of F with argument "
prototype
".5) If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
Here we see the real power of new
: if the constructor function does not return an object (and therefore the [[Construct]]
operation launched by new
is allowed to return obj
), then prototypal inheritance takes place. The [[Prototype]]
of obj
(a.k.a. obj.__proto__
) is set to the prototype
property of the constructor method. This means that if foo
doesn't return an object (and instead modifies this
), and foo.prototype.someProp
is set, then an instance returned from var instance = new foo()
will have access to instance.someProp
.
Thus, a different way to write your code might be:
var foo = function() { };
foo.prototype.setA = function(a) { this.a = a; };
foo.prototype.setA = function(a) { console.log(this.a); };
In this case, new foo()
produces an object whose prototype chain includes foo.prototype
, while foo()
does not. This has the benefit of lower memory use: all foo
instances here share common prototypal methods, instead of having each instance carry its own separate functions.
Upvotes: 1
Reputation: 664513
i'm still in the fog about
new
; let's talk about this example :var foo = function() { return { setA: function(a) { this.a = a; }, readA: function() { console.log(this.a); } }; };
We shouldn't talk about this example. Whether or not we use new
with this function does not make a difference, because of the way new
works:
- A new object is created, inheriting from
foo.prototype
.- The constructor function
foo
is called with the specified arguments andthis
bound to the newly created object.- 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 step 1 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.)
Step 3 is the thing to look at here. You're creating and returning an object (the object literal), so that will become assigned to bob1
. Usually, constructor functions do not return
anything, and the new instance that is implicitly created in step1 (and available inside the function as this
) becomes the result.
Both new foo()
and foo()
do only assign your object literal to the bob
variable - no difference in the result. The instance created by the new
is totally ignored by your code. It would be different in the following examples:
function foo() {
this.setA = function(a) {
this.a = a;
};
this.readA = function() {
console.log(this.a);
};
// return this; is implicit
}
var bob = new foo; // OK
var bob = foo(); // horrible error
Upvotes: 3
Reputation: 92745
If your function returns object directly, then you do not need an new
operator.
The new
keys does more than that.
Lets say
function Animal(kind, name) {
this.kind = kind;
this.name = name;
}
Animal.prototype.walk = function() {
console.log('Walking');
}
Then you are doing
var animal = new Animal();
Javascript engine will do following things
var o = Object.create(Animal.prototype)
Animal.apply(o, arguments);
return o;
Object.create
will do the prototype inheritance of the prototype
object of Animal
function. So animal
object will have its own properties and its inherited property.
Upvotes: 4