8

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" ?

Community
  • 1
  • 1
  • 3
    Related: [Constructor function vs Factory functions](http://stackoverflow.com/questions/8698726/constructor-function-vs-factory-functions) – Qantas 94 Heavy Apr 08 '14 at 09:37
  • I think it is related to this http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript – dudung Apr 08 '14 at 09:39
  • 1
    @3506238: the OP has already read that. – Qantas 94 Heavy Apr 08 '14 at 09:39
  • BTW, the post you read before has a lot of useful information, you just need to scroll down to see some of the easier-to-understand answers. For example, this one: http://stackoverflow.com/a/1646957/2074608 – Qantas 94 Heavy Apr 08 '14 at 09:40
  • 1
    The difference is in scope of the function. You don't see any difference because you don't refer to the `this` in the scope of the function. You only refer to the `this` in the scope of the returned object which is the same in both cases. – Molecular Man Apr 08 '14 at 09:41
  • In the given example there is no difference, the advantage of creating new instances comes when you need to create new instances that can be changed and worked with without affecting other instances etc. – adeneo Apr 08 '14 at 09:41
  • @MolecularMan: `this` is not the *scope*, it's the *context* of a function! – Bergi Apr 08 '14 at 09:46
  • @Bergi I didn't say this=scope, did I? – Molecular Man Apr 08 '14 at 09:47
  • @Bergi, yeah I meant context. – Molecular Man Apr 08 '14 at 09:49
  • @MolecularMan: Oh right. Maybe in the first sentence; I expected "*The difference [between `new` and not] is what `this` is in the constructor function*". If you're just saying that he uses `this` in the wrong function, then yes. – Bergi Apr 08 '14 at 09:49
  • @Bergi, yeah. What I meant wat that `this` refers to different objects when used as constructor and plain function, but wasn't able to pick wright words. – Molecular Man Apr 08 '14 at 09:57

3 Answers3

4

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.

Fizer Khan
  • 71,869
  • 26
  • 133
  • 149
3

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:

  1. A new object is created, inheriting from foo.prototype.
  2. The constructor function foo is called with the specified arguments and this bound to the newly created object.
  3. 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
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
1

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 the this 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.

apsillers
  • 101,930
  • 15
  • 206
  • 224