What is the purpose of the 'new' keyword in JavaScript?

After years of using JavaScript like a semi-imperative version of Lisp, I am still confused about how constructors actually work in the language. I would appreciate some insight into how objects are meant to function in JavaScript.

Consider this code snippet:

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

I'm curious to know what sets myFoo = Foo(5) apart from myFoo = new Foo(5). In essence, what is the role of a constructor in JavaScript?

Answer №1

What is the distinction between using myFoo = Foo(5) versus myFoo = new Foo(5)?

In this scenario, there actually isn't a difference because both methods result in an object being returned. According to the specification:

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

Since the function returns an Object as its result, either method can be used interchangeably. A discrepancy would only arise if it did not return an object or if it checked this, such as in this example:

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 exactly does the new operator do in JavaScript?

The new operator results in the function being invoked with this bound to a freshly created Object whose prototype is the function's prototype property.

For user-defined functions,

new f(a, b, c)

is essentially equivalent to

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

// Invoke 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

It's important to note that the language specification defines functions with two operations, [[Call]] and [[Construct]], which leads to some peculiar behaviors when using new.

For instance, bound and built-in functions:

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

should create a function that merely calls f; thus, g should behave identically to f. However, when doing:

new g()

a

TypeError: function call() { [native code] } is not a constructor
error occurs since the built-in function Function.prototype.call supports [[Call]] but not [[Construct]].

Additionally, Function.prototype.bind displays different behavior between new and regular calls. The this value is always the bound thisValue during a regular call, whereas it becomes a newly constructed instance when using new.

Answer №2

In this specific instance, there is no disparity in the final outcome.

This occurs because the function Foo is giving back an object instance.

The new operator yields a newly formed object that inherits from the constructor's prototype only when the function produces a primitive value (or if it doesn't produce any result, which technically represents the undefined value).

For instance:

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 hand back an object, the freshly created object that borrows from the constructor's prototype is simply disregarded:

function Foo () {
  return {};
}

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

Also refer to:

  • What values can a constructor return to avoid returning this?
  • JavaScript: How does 'new' work internally

Answer №3

When you create a new object in this case, there won't be any difference. You could rephrase it like this:

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

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

Using this syntax, each time new Foo is called, a new object with a property of _x will be created. The advantage is that the bar function will only be stored once and can be used for multiple instances of Foo. In contrast, if you call Foo() multiple times as shown in the code, a separate bar function will be created for every instance. Therefore, attaching functions to the prototype rather than directly on the object will consume less memory.

You can find a detailed explanation of how prototypes work here at MDN.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for including a footer element in React:How can a footer division be

I need help with implementing a footer in my React web app. Currently, the body section in index.html looks like this: <body> <div id="root"></div> <script src="index.js"></script> </body> Inside index.js, the rend ...

Discover the power of EJS embedded within HTML attributes!

There are two cases in which I am attempting to use an EJS tag within an HTML attribute. SITUATION 1: <input style="background-image: url(<%= img.URL %>)" /> SITUATION 2: <input onchange="handleCheckboxChange(<%= i ...

The functionality of module.exports and require operation

My understanding of module.exports and require() in NodeJS is a bit unclear, leading me to seek help finding answers. I can export functions like: example1.js module.exports = { hello: function() { return 'Hello world'; }); } O ...

The debate between CSS Generic loading and Page Specific loading has been a

Seeking advice on optimizing CSS placements to improve website load times. I've learned about the concept of 'critical CSS' in the head section and other styles in the body using link tags. Is it advisable to load shared 'Generic' ...

What is the best way to access the original observed node using MutationObserver when the subtree option is set to

Is there a way to access the original target node when using MutationObserver with options set to childList: true and subtree: true? According to the documentation on MDN, the target node changes to the mutated node during callbacks, but I want to always ...

express.js and socket.io compatibility perplexity

Server-Side Code: var server = require("http").Server(express); var io = require("socket.io")(server); server.listen(5000); io.on('connection', function(client) { client.on('order', function(data) { io.emit('place_orde ...

Tips on avoiding duplicate selection of checkboxes with Vue.js

Recently delving into vue.js, I encountered a challenge with multiple checkboxes sharing the same value. This resulted in checkboxes of the same value being checked simultaneously. How can this issue be resolved? var app = new Vue({ el: '#app&apo ...

Creating a grid with React and implementing lodash

I am having trouble displaying a simple grid in my test project. I didn't want to manually create the grid because it would be cumbersome for larger grids and clutter up the code, so I decided to use lodash. However, no matter what I try, I can' ...

Mastering MaterializeCSS: Creating a Toggle Feature for Two Notifications with a Single Button Click

Visit my Personal Website at this Link StyleSource-Library BETA While I was working on some content, I created a Container Enabler/Disabler Button. This button is positioned in the Navigation Bar on the top right and works perfectly by adding a container ...

Adjusting the label on the Formik toggler

I have successfully implemented a switcher using Formik that changes the label accordingly with a boolean value. However, I now need to make the label reflect a string value instead of just "true/false." For example, I want it to display "Text1/Text2" inst ...

"An issue with the external jQuery file loop causes it to skip either the first or

I have a webpage where I am dynamically loading content from an external JavaScript file. This file identifies div elements with a specific class name and then fills the content of those divs based on a custom attribute, which contains a link to an API. Th ...

Ways to replicate a key press event upon the loading of a document

Seeking assistance with automatically focusing on a specific div that is the only part of the page with a scrollbar. I have researched using a jQuery function and simulating a keypress (tab) on document load without success. Any guidance or solution to t ...

changing the default property value within an object

I'm looking to send an ajax request to a PHP file that will retrieve a user's information in JSON format. I then want to take this data and assign it to a property within an object. For example: User = { prop1: '' } I simply need to ...

Updating the content of a file on an iPhone

Is there a way to update the entire document content with a response from an ajax request? I've tested out using document.body.innerHTML and document.write(), which both work on desktop Safari. However, I'm looking for a solution that will also ...

Is there a way to dynamically update the button color within JavaScript and have it reflect in a separate function?

I have been working on developing a button effect in JavaScript that can be called within another function. The idea is that when the button is clicked, it will change color, and then revert back to its original color. While this could be achieved using th ...

Choose a numeric value and then adjust it to display with exactly two decimal places

My goal is to create a code that achieves the following tasks: Add an ID to every nth child Round the number in each nth child to 2 decimal places Prefix the numbers with a pound sign (£) Loop through until all the nth children in a table are processed ...

After npm installation and running the dev command, an error is displayed in the console, despite the project functioning properly on a different

After successfully installing a reliable project on my personal computer and compiling it without any issues, I encountered an error message in the console. Uncaught ReferenceError: regeneratorRuntime is not defined at eval (index.umd.js?e3f3:5) at eval ( ...

Issue with activation of onClick event in case/switch statement

Currently working on a JavaScript project to recreate the Fallout terminal game, with one of the main aspects being comparing words selected by the user to those chosen by the computer. The concept of this hacking game is reminiscent of the board game Mas ...

Troubleshooting Problem in Coursera's AngularJS Week 3 Exercise 4

Here's the issue I'm facing: After launching the index page with 'gulp watch', there's nothing visible on the screen. An error appears: Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.4.12/$injector/modulerr?p ...

jQuery code runs smoothly on Firefox but encounters issues on Chrome

I'm experiencing an issue with a script that is supposed to post a comment and load the answer from a server. The script works fine in Firefox, but in Chrome, it seems that no event is triggered. You can click the button, but nothing happens. I'v ...