What is the 'new' keyword in JavaScript?
It does 5 things:
- It creates a new object. The type of this object is simply object.
- 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).
- It makes the
this
variable point to the newly created object. - It executes the constructor function, using the newly created object whenever
this
is mentioned. - 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 Functionprototype
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.
- If the function's
- 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)
andmyFoo = 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)
isObject
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:
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:
- Functions created using the
function
keyword (excluding generator functions) - Classes (which can be treated as functions)
- Bound function exotic objects ("bound functions")
- Some host objects
- 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):
- A new object
o
is created - The
[[Prototype]]
("the prototype") ofo
is set to the value of the.prototype
property of the constructor (note this means the.constructor
property is inherited by the new object) - The target (ie
this
) of the constructor body is set too
- The constructor is run with the
this
value defined above - 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:
Create a new object
Add
__proto__
property on the newly created object that points toFruit.prototype
object.Point
this
inside theFruit
constructor to the newly created object.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
Split a String by Commas But Ignore Commas Within Double-Quotes Using JavaScript
How to Programmatically Click a Link with JavaScript
What's the Fastest Way to Loop Through an Array in JavaScript
Is This an Example of Variable Shadowing in JavaScript
Hide Scrollbar While Still Being Able to Scroll with Mouse/Keyboard
Adding Multiple Event Listeners to One Element
How Filereader.Readastext in HTML5 File API Works
Syntax Highlighting Code with JavaScript
Jquery Select Option Click Handler
Add Event Listener on Elements Created Dynamically
What's the Difference Between & and && in JavaScript
Redirect Parent Window from an Iframe Action
Fetch Request to Local File Not Working
How to Figure Out the Highest Z-Index in Your Document
How to Change CSS :Root Color Variables in JavaScript