How Does the New Operator Work in JavaScript

What is the 'new' keyword in JavaScript?

It does 5 things:

  1. It creates a new object. The type of this object is simply object.
  2. It sets this new object's internal, inaccessible, [[prototype]] (i.e. __proto__) property to be the constructor function's external, accessible, prototype object (every function object automatically has a prototype property).
  3. It makes the this variable point to the newly created object.
  4. It executes the constructor function, using the newly created object whenever this is mentioned.
  5. It returns the newly created object, unless the constructor function returns a non-null object reference. In this case, that object reference is returned instead.

Note: constructor function refers to the function after the new keyword, as in

new ConstructorFunction(arg1, arg2)

Once this is done, if an undefined property of the new object is requested, the script will check the object's [[prototype]] object for the property instead. This is how you can get something similar to traditional class inheritance in JavaScript.

The most difficult part about this is point number 2. Every object (including functions) has this internal property called [[prototype]]. It can only be set at object creation time, either with new, with Object.create, or based on the literal (functions default to Function.prototype, numbers to Number.prototype, etc.). It can only be read with Object.getPrototypeOf(someObject). There is no other way to set or read this value.

Functions, in addition to the hidden [[prototype]] property, also have a property called prototype, and it is this that you can access, and modify, to provide inherited properties and methods for the objects you make.


Here is an example:

ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes
// it a constructor.

ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that
// we can alter. I just added a property called 'b' to it. Like
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with

obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1. At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.

obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'

It's like class inheritance because now, any objects you make using new ObjMaker() will also appear to have inherited the 'b' property.

If you want something like a subclass, then you do this:

SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);

SubObjMaker.prototype.c = 'third';
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype

obj2.c;
// returns 'third', from SubObjMaker.prototype

obj2.b;
// returns 'second', from ObjMaker.prototype

obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype
// was created with the ObjMaker function, which assigned a for us

I read a ton of rubbish on this subject before finally finding this page, where this is explained very well with nice diagrams.

How does the new operator work in JavaScript?

The new operator uses the internal [[Construct]] method, and it basically does the following:

  • Initializes a new native object
  • Sets the internal [[Prototype]] of this object, pointing to the Function prototype property.

    • If the function's prototype property is not an object (a primitive values, such as a Number, String, Boolean, Undefined or Null), Object.prototype is used instead.
  • After creating the object, it calls the function, providing the object as its this value.
  • If the return value of the called function, is a primitive, the object created internally is returned.
  • Otherwise, if an object is returned, the object created internally is lost.

An equivalent implementation of what the new operator does, can be expressed like this (assuming that the ECMAScript 5 Object.create method is available):

function NEW(f) {
var obj, ret, proto;

// Check if `f.prototype` is an object, not a primitive
proto = Object(f.prototype) === f.prototype ? f.prototype : Object.prototype;

// Create an object that inherits from `proto`
obj = Object.create(proto);

// Apply the function setting `obj` as the `this` value
ret = f.apply(obj, Array.prototype.slice.call(arguments, 1));

if (Object(ret) === ret) { // the result is an object?
return ret;
}
return obj;
}

// Example usage:
function Foo (arg) {
this.prop = arg;
}
Foo.prototype.inherited = 'baz';

var obj = NEW(Foo, 'bar');
obj.prop; // 'bar'
obj.inherited; // 'baz'
obj instanceof Foo // true

What does `new` in JavaScript do, anyway?

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.

JavaScript functions and the new operator

Firstly, we know that functions are nothing but objects as we can attach properties to it. That is what is happening in the case1.
We are just simply attaching a property to a function Foo

Case 1

var Foo = function(){
this.name = "myname";
}

Foo.newProp = function(){};

The property attached to the function can be simply accessed as how we access properties of an object.

Case 2

In this case the same property is sitting on the prototype of that function. When any object is created using this function Foo, it will get access to this function by default.

When calling the function using that object, the context this will know the object calling that function and this points to the object calling it.

Foo.prototype.newProp = function(){ console.log("function on prototype");}

var value = new Foo();

console.log(value);

Also in case 2, since we are adding properties to the prototype of the function, they are not sitting on the object made using that function but on the proto of that object. Check this screenshot shown below:

Sample Image

That means there is a common memory location to which every object accessing that property will be pointing and hence it is memory efficient as well.

You can always go ahead and modify that property by overriding it by defining it directly on the object as:

value.newProp = function(){ console.log("modified property") };

Now, if you call this function, it will find it directly on the object and wont go down the prototype chain to access it from the common memory location i.e prototype of the function Foo

javascript: what do the new keywords do internally

The new-able objects in JavaScript are:

  1. Functions created using the function keyword (excluding generator functions)
  2. Classes (which can be treated as functions)
  3. Bound function exotic objects ("bound functions")
  4. Some host objects
  5. Proxies if they are applied to one of the above

I know this because the only object types the new operator works with are "constructors" (specification term). A constructor is an object with a [[Construct]] internal method, and you can search the ECMAScript specification to find out which kinds of object have a [[Construct]] internal method.

To make the result of a constructor function new-able, therefore, you must return one of the object kinds listed above.

Note that the specification specifically says that all constructors are definitionally functions because they must support the [[Call]] internal method (note also the caveat below about host objects).

If you want to get very advanced, then you may be interested to learn that host objects do not appear to share the ordinary limitations for constructors (presumably for legacy Web compatibility reasons), but these are exceptional.

Explanation of the .constructor property

When a new-able function f is declared, two objects are created: the function-object f itself, and a default object on the .prototype own-property of f. The .constructor property of this default .prototype object is automatically set by the runtime to be f. I believe classes work in a very similar fashion. Note that the fact that the name of this property was chosen to be "prototype" makes discussing prototypes quite confusing in JavaScript (as it is distinct from the [[prototype]] of the function).

This constructor own-property on the object positioned on the .prototype property, is never read by any built-in function or operation (that I know of). I view it as vestigial from the earliest days of JavaScript - it's original intent was as a way to maintain a link between the "class" that constructed an object as a developer affordance. Host environments (eg browsers) sometimes use it to infer the "type" of an object for the purposes of communicating with the user (eg. console output), the property is writeable and therefore unreliable.

Steps performed by the new operator

At a high level, when new is invoked against a constructor, the following steps occur (spec contains full details):

  1. A new object o is created
  2. The [[Prototype]] ("the prototype") of o is set to the value of the .prototype property of the constructor (note this means the .constructor property is inherited by the new object)
  3. The target (ie this) of the constructor body is set to o
  4. The constructor is run with the this value defined above
  5. If there is no explicit object-type return value, then o is returned by default

Javascript new keyword

No, this does not create a new instance of Person and then call a method on it. It creates an instance of whatever Person.doSomething() is. So, in effect, you these two are equivalent:

const Person = {  doSomething: function(foo, bar){    this.foo = foo;    this.bar = bar;  }}
//create a new instance of `Person.doSomething`const p1 = new Person.doSomething(1, "one");
//take a reference of `Person.doSomething`const temp = Person.doSomething;//create an instance of itconst p2 = new temp(2, "two");
console.log("p1:", p1);console.log("p1 instanceof Person.doSomething:", p1 instanceof Person.doSomething);
console.log("p2:", p2);console.log("p2 instanceof Person.doSomething:", p2 instanceof Person.doSomething);

Omitting 'new' keyword causing unexplainable problems in javascript constructor function

Value of this depends on how the function is called.

In non-strict mode, when you call the altFruit function without the new keyword, this inside it will refer to the global window object. So,

this.person = person;

will add person property on the global window object. (you can test this by logging window.person on the console at the end of your code).

When you call aFunction, in non-strict mode, value of this inside displayInfo function will refer to the global window object.

In short, your code is adding and reading properties to and from the global window object, respectively.

The "new" operator

new operator is used to create instances of user-defined object types (like Fruit) or built-in object types (like Array, Date, etc).

When you call new Fruit(...), new operator will do the following things:

  1. Create a new object

  2. Add __proto__ property on the newly created object that points to Fruit.prototype object.

  3. Point this inside the Fruit constructor to the newly created object.

  4. Return the newly created object from the Fruit constructor function.

For more details, see: MDN: new operator

In javascript, does the new operator always return an object of same type which is mentioned in the new statement?

When you return a primitive (say 2) from a constructor, the return value is ignored. The object created by new is returned instead, just like when a constructor has no return statement. If you return an object from a constructor, the object is returned (note: functions are objects in Javascript), whether or not that object has the constructor as its internal prototype.

In your case you are returning a function; that function is foo, but it is not an instance of foo.

See new operator



Related Topics



Leave a reply



Submit