Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does `new` in JavaScript do, anyway? [duplicate]

Tags:

javascript

oop

I am very confused about how constructors work in Javascrpt; despite using the language for several years (mostly as if it were like a semi-imperative version of LISP) I would like to know more about how objects are supposed to work in it.

Given this code:

function Foo(x) {
    return {
        bar: function() { return x; }
    };
}

What is the difference between calling myFoo = Foo(5) and myFoo = new Foo(5)? Or, in other words, what exactly does a constructor in Javascript do?

like image 528
fluffy Avatar asked Feb 27 '12 16:02

fluffy


People also ask

What does the new do in JavaScript?

New keyword in JavaScript is used to create an instance of an object that has a constructor function. On calling the constructor function with 'new' operator, the following actions are taken: A new empty object is created.

What does the new keyword do?

The new keyword in JavaScript: The new keyword is used to create an instance of a user-defined object type and a constructor function. It is used to constructs and returns an object of the constructor function.

Why is JavaScript running twice?

It's because a <label> with a for attribute raises the click event of <input type="checkbox"> element that is associated for when clicked. You should bind click event handler to input , not to label . Show activity on this post. When you click your label, may it be there is event click runs also on checkbox?


3 Answers

What is the difference between calling myFoo = Foo(5) and myFoo = new Foo(5)?

There's no difference for that code, because it returns an object, and the spec says:

  • Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
  • If Type(result) is Object then return result.

Since that function returns a result that is an Object, its result is used. You would notice a difference if it did not return an object, or if it checked this, for example if you rewrote it as:

function Foo(x) {
  if (!(this instanceof Foo)) { return new Foo(x); }
  this.bar = function() { return x; };
}
// Now instanceof works.
alert((new Foo) instanceof Foo);

What does new in JavaScript do, anyway?

The new operator causes the function to be called with this bound to a newly created Object whose prototype is that function's prototype property.

For user-defined functions,

new f(a, b, c)

is equivalent to

// Create a new instance using f's prototype.
var newInstance = Object.create(f.prototype), result;

// Call the function
result = f.call(newInstance, a, b, c),

// If the result is a non-null object, use it, otherwise use the new instance.
result && typeof result === 'object' ? result : newInstance

Note, that the language specification actually defines functions with two operations, [[Call]] and [[Construct]], so there are some corner cases where new behaves oddly.

For example, bound and built-in functions:

var g = f.call.bind(f);

should define a function that when called, just calls f, so g should be the same as f in all respects, but

new g()

produces

TypeError: function call() { [native code] } is not a constructor

because the builtin function Function.prototype.call supports [[Call]] but not [[Construct]].

Function.prototype.bind also behaves differently around new and regular calls. The this value is always the bound thisValue when called, but is a newly constructed instance when you use new.

like image 52
Mike Samuel Avatar answered Oct 19 '22 04:10

Mike Samuel


In this particular example, there's no difference in the end result.

This is because your Foo function is returning an object instance.

The new operator returns a newly created object that inherits from the constructor's prototype only when the function returns a primitive value (or it doesn't return anything, which is technically the undefined value).

For example:

function Foo () {
  return 5; // or "", or null, or no return statement at all (undefined)
}

var foo = new Foo();
typeof foo; // "object"
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true

When you return an object, the newly created object that inherits from the constructor's prototype is simply discarded:

function Foo () {
  return {};
}

var foo = new Foo();
typeof foo; // "object"
foo instanceof Foo; // false
Foo.prototype.isPrototypeOf(foo); // false

See also:

  • What values can a constructor return to avoid returning this?
  • JavaScript: How does 'new' work internally
like image 27
Christian C. Salvadó Avatar answered Oct 19 '22 04:10

Christian C. Salvadó


In this instance there will be no difference as you are returning a new object. It could be rewritten as:

function Foo(x){
   this._x = x;
}

Foo.prototype.bar = function() { 
   return this._x;
}

With this syntax each time you call new Foo it will create a new object with a property of _x. The benefit is that the bar function will be stored once and reused for multiple instances of Foo. With the code in the question calling Foo() multiple times will create a bar function for every instance. So attaching functions to the prototype rather than having them directly on the object will be lighter in memory.

A full break down of how the prototype works can be found at MDC.

like image 6
slashnick Avatar answered Oct 19 '22 04:10

slashnick