Pattern for enforcing new in javascript rating not rated
SoftXML
                  Programming Books
                Open Web Directory
           SoftXMLLib | SoftEcartJS
xml products   Home page    contact    site map
Contact Us
Latest Blog Articles:   Latest SEO Articles | RSS Feed
DOM manipulation best practices
JavaScript Module Pattern
How to start developing with the Nextjs
Angular application structure
Write Guest Articles
Articles Archive




Loading...

The Art & Science of JavaScript ($29 Value FREE For a Limited Time)
The Art & Science of JavaScript ($29 Value FREE For a Limited Time)









Pattern for enforcing new in javascript


Constructors are ordinary functions that are called using the new operator. What happens if you forget to add the new operator when calling the constructor?

This will not be interpreted by the interpreter as an error, but may lead to a logical error and unexpected results. If you call the constructor without the new operator, the this inside the constructor will point to the global object. (In browsers, this will point to a window object.)

If a new property is created in the constructor, such as this.member, then when the constructor is called without the new operator, a new member property of the global object will be created, which can be accessed like this: window.member or just member.

This constructor behavior is highly undesirable because you should always fight for the cleanliness of the global namespace: (you can change the code in the sandbox below and then press execute button):

This unwanted behavior is eliminated in the ECMAScript 5 standard, and in strict mode, this no longer points to a global object.

But if the ES5 implementation is not available, you can still take certain actions, thanks to which the function will always act as a constructor, even when called without the new operator.

Naming conventions

The easiest option is to use naming conventions, according to which the names of the constructors begin with an uppercase character (MyConstructor), and the names of "ordinary" functions and methods with a lowercase character (myFunction).

Using that

Following naming conventions is, of course, useful, but conventions are just a hint and not ensuring correct behavior. The following describes a template that ensures that your constructors always behave like constructors. The bottom line is, instead of the this, add new members to the that and return it explicitly.


function Car() {
 var that = {};
 that.color = “red”;
 return that;
}

When creating simple objects, you don’t even need a local variable, like that in our example, you can simply return an object defined as a literal:

When calling the constructor function with the new operator, the following happens inside the function:


function Car() {
 return {
   color: 'red'
 };
}

Any of the above Car() implementations will always return an object no matter how this function is called: (you can change the code in the sandbox below and then press execute button):

The problem with this approach is that the connection with the prototype will be lost, so all members added to the Car() function`s prototype will be inaccessible to objects.

Note that the variable name that is only selected for convenience - it is not part of the language. As well you can use any other name. Common names include self and me.

Here is the preferred solution - Constructors calling themselves

To get rid of the drawback inherent in the previous template, and to ensure the availability of prototype properties in instances of the object, you can use the following solution.

In the constructor, you can check whether the this reference is an instance of the constructor, and if not, call the constructor again, but with the new operator (you can change the code in the sandbox below and then press execute button):

Another common way to validate an instance is to compare, not with a specific constructor name, but with a property arguments.callee.


if (!(this instanceof arguments.callee)) {
 return new arguments.callee();
}

This template uses the fact that an object called arguments is created inside each function, containing all the parameters passed to the function when called.

The arguments object has a callee property that refers to the called function. However, keep in mind that the arguments.callee property is not available in ES5 strict mode, so it`s best to refrain from using it in the future.

Tag cloud

'red'

((this

(you // Car()

Car(); alert(typeof

ES5

arguments

available

behavior called calling change

character

check

code

color

constructor constructors conventions created

error

execute function

functions

global

good_car

good_car);

happens

inside

instance

instanceof

members

mode

name names

naming

object operator
Rate This Article
(votes 4)

Comments (2) comments

Michael J. Ryan Mar 29, 2020 at 03:04

First, if you use the class syntax, then you will get an error if you don`t use new.

    class Foo {
      // implementation details go here
    }

    Foo(); // Error: Class constructor Foo cannot be invoked without `new`

Second, you can do the same kind of behavior in a constructor function.

    function Foo() {
      if (!(this instanceof Foo)) {
        throw new Error("Class constructor Foo cannot be invoked without `new`");
      }
      // implementation details go here
    }

The article does discuss the issue, but gives no real resolution, such as above.

The article`s solution break the type for the returned object... you may as well not use a constructor/class at all if that`s your approach, which is fine, but don`t use a constructor function naming `Foo` if you`re returning a custom object, use `createFoo` or another appropriate name.

Alternatively...

    function Foo(...args) {
      if (!(this instanceof Foo)) {
        return new Foo(...args);
      }
      ...
    }

Gregory Mar 29, 2020 at 03:20

Hi Michael

You are absolutely right for pointing out this important issue about losing prototype chain! I wrote about this problem at the very end of the article and now added optimal solution by using method of Constructors calling themselves.

Thanks!


Post Comment

We love comments on this blog - they are as important as anything we write ourself. They add to the knowledge and community that we have here. If you want to comment then you�re more than welcome � whether you feel you are a beginner or an expert � feel free to have you say.



* = required
Leave a Reply
Name *:
Email *
(will not be published):
Website:
Comment *:
Human Intelligence Identification *:
What is the background color of this web page?
  
Close
Please enter a valid email Please enter a valid name Please enter valid email Please enter valid name Enter valid year
™SoftXML.   Privacy Statement  |  Article Archive  |  Popular Web Development Books
^Top