Is it necessary to use the "new" keyword when utilizing JS closure to create objects?

My response to a question about closures on SO included the following code sample:

function Constructor() {
    var privateProperty = 'private';
    var privateMethod = function(){
        alert('called from public method');
    };
    return {
        publicProperty: 'im public',
        publicMethod: function(){
            alert('called from public method');
        },
        getter: privateMethod
    }
}

var myObj = new Constructor();

//public
var pubProp = myObj.publicProperty;
myObj.publicMethod();
myObj.getter();

//private - will cause errors
myObj.privateProperty
myObj.privateMethod

A user left a comment on my answer which said:

Also, if your function explicitly returns an object it is not a good practice to call it with new because that is misleading - if using new you'd expect the result to be an instance of Constructor

I typically create objects using new. But why is it considered not a good practice? It appears that using new and not using new both return the same thing. What is the correct way to create objects from closures?

Answer №1

It's important to note that the use of instanceof can yield unexpected results, as demonstrated below:

function C1() {
    return {};
}

function C2() {
}

var c1 = new C1();
var c2 = new C2();
alert(c1 instanceof C1); // false; unexpected result
alert(c2 instanceof C2); // true, expected result

Here's a demo.

To avoid such issues, it's recommended to create objects by assigning to this, with added safeguards to prevent missing new calls.

function Constructor() {
    var privateProperty = 'private';
    var privateMethod = function() {
        alert('Called from private method');
    };

    this.publicProperty = "I'm public!";
    this.publicMethod = function() {
        alert('Called from public method');
    };
    this.getter = privateMethod;
}

An even more efficient approach is to utilize prototypes whenever possible:

function Constructor() {
    var privateProperty = 'private';
    var privateMethod = function() {
        alert('Called from private method');
    };

    this.getter = privateMethod;
}

Constructor.prototype.publicProperty = "I'm public!";
Constructor.prototype.publicMethod = function() {
    alert('Called from public method');
};

Answer №2

When examining point 4 in this response: Understanding the concept of the 'new' keyword in JavaScript

"The outcome is the newly formed object, unless the constructor function yields a non-primitive value. In such scenario, that non-primitive value will take precedence."

Hence, following minitech's explanation where function C1 delivers an empty object, the variable c1 will correspond to the returned object instead of the one generated by the 'new' declaration. Consequently, no instance of the constructor function is created.

In case I attempt to return a primitive value from the constructor function, my webstorm issues a notice: "If invoked with new, the intended value will not be preserved and an object will be delivered as the result instead."

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

The 'xxx' type is lacking various properties compared to the 'xxx[]' type, such as length, pop, push, concat, and many others

Utilizing typescript and reactjs, the issue lies within this component import type { InputProps } from "../utils/types" const Input = (props: InputProps) => { const makeChildren = () => { return ( <> ...

Interact with USB drive using electron to both read and write data

I am currently developing an electron project that involves copying files from a computer to USB drives. I need the ability to transfer files and folders to the destination USB drive, as well as determine the amount of free space on the drive. I have expe ...

Finding clarity amidst the chaos of require and export in Express.js (Node.js)

Is there a way to make my socket.io connection modular so that it can run once and be accessible anywhere? How can I export it? var server = require("http").Server(express); var io = require("socket.io")(server); server.listen(5000); io.on('connect ...

Animating content through CSS and jQuery to reveal its unfolding effect

Just stumbled upon the amazing quote-expansion animation in the OSX Mail app and I am completely impressed. I am on a mission to bring that same magic to the web (or at least close to it), but unsure if anyone has done something similar yet. A couple of ...

How can I access specific values from a table generated with a PHP array using jQuery?

Currently, I am working on a page where users can upload documents. Once uploaded, these docs are stored in a folder and their location is updated in a table for reference. Now, when I navigate to an edit page, I use PHP to query the database and display t ...

Managing the layout with React Native Flexbox to evenly distribute items

Check out this React Native Demo I put together featuring Santa images being added and removed in a Flexbox. Bunch of Santas I noticed that when there are more than 3 Santas, the layout shifts to the left. I'm curious about how to keep the Santas ce ...

Insert the URL into either a div or an iframe

It seems like a common issue. I've come across multiple solutions for this problem. using jquery load using iframe I attempted both methods but encountered difficulties in loading content. Specifically, I tried to load google.com and it didn't ...

Looking for assistance with reviewing and optimizing Angular UI-Router implementation

I'm currently facing an issue with setting up routing for my angular portfolio. Despite checking my code against a previous app, I am unable to identify the error as there are no console logs when I compile. Can someone please review my code layout an ...

Automatically substitute a term with a clickable link

Is there a way to automatically turn every word into a hyperlink? I have specific words that need to be linked. For example, I want Ronaldo (Only for the First Appearance) to link to a certain page. However, my attempted method did not work. <p> Ro ...

Adjust the height of a div using jQuery animate based on the amount of text within

I have created a basic animation feature where users can click on an expanding box. I am looking for a solution that does not involve using a plugin. Currently, the code looks like this: $('#one').css("height", "22"); $('#t1').cli ...

Another class is overriding the border of the text-box

I'm facing a challenge in customizing the material ui css. Specifically, I want to set the border color of a textbox to red. The issue arises when the bottom border gets overwritten. Upon investigation, I discovered that the culprit is the class MuiIn ...

Clear the Material-UI textfield upon form submission

After submitting the form, how can I clear the value from the TextField? All of the components in my code are functional components, not class ones. The example below shows one of the TextFields, with others similar to it. Currently, setting type='sea ...

Ways to store information using VueJS lifecycle hooks

I am currently working on setting a data property using the created lifecycle hook within my component. The issue I'm encountering is receiving a "TypeError: Cannot read property 'summary' of undefined" in the console as I run the code. This ...

Adjusting the position of a stationary element when the page is unresponsive and scrolling

Managing a large web page with extensive JavaScript functionality can be challenging, especially when dealing with fixed position elements that update based on user scroll behavior. A common issue that arises is the noticeable jumping of these elements whe ...

Utilize a vacant implementation of an interface

I have a simple interface called EmployerContact. I'm wondering how I can create an empty object, mockEmployerContact, of type EmployerContact and then assign values to its properties later on. Do I need to start with default values for this object? e ...

Leveraging ThemeProvider Parameters with Global Styled-Components

When working with styled-components, how can I access the props of the ThemeProvider in the context of global.js? For instance, in my theme.js file, I have ${props => props.theme.fonts.fontSize} set to a default font size of 16px. const theme = { ...

Next.js React Hydration Issue - "Anticipated a corresponding <a> within the server HTML <a>"

Currently, I am encountering a hydration error while working on my Next.js project. The specific error message that keeps popping up is: Error: Hydration failed because the initial UI does not match what was rendered on the server. Warning: Expected serv ...

Refine the search outcomes by specifying a group criteria

I have a scenario where I need to filter out service users from the search list if they are already part of a group in another table. There are two tables that come into play - 'group-user' which contains groupId and serviceUserId, and 'gro ...

NodeJS: Retrieve Over 10,000 Images From the Server

Attempting to retrieve over 10,000 images from a server led me to create this script: const http = require('http') const fs = require('fs') const opt = { agent: new http.Agent({ keepAlive: true, maxSockets: 5 }), headers ...

What are the steps for encountering a duplicate property error in TypeScript?

I'm currently working with typescript version 4.9.5 and I am interested in using an enum as keys for an object. Here is an example: enum TestEnum { value1 = 'value1', value2 = 'value2', } const variable: {[key in TestEnum]: nu ...