Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern for enforcing new in javascript

Tags:

javascript

I have been reading JavaScript Patterns book by Stoyan Stefanov and one of the patterns to enforcing the new operator for constructor functions goes like this

function Waffle() {
if (!(this instanceof Waffle)) {
return new Waffle();
}
this.tastes = "yummy";
}
Waffle.prototype.wantAnother = true;

when writing this way you can invoke Waffle either one of these ways

var first = new Waffle(),
second = Waffle(); 

I think this is a helpful feature not sure if it's implemented in future versions of ecma/javascript

I came up with something on my own that I thought could just copy and paste each time when creating a constructor function

something like this

function checkInstance (name) {
    if (name.constructor.name === undefined) {
       return "construct it"
    } else {
       return false;
    }
}

function Waffle() {
    var _self = checkInstance.call(this, this);
    if (_self === "construct it") {
       return new Waffle()
    }
    this.tastes = "yummy"
}

var waffle = Waffle()
waffle

Therefore I can invoke Waffle either way new Waffle or Waffle() and still have it return an object

My problem that I'm having is here

  if (_self === "construct it") {
       return new Waffle()
       }

Is there anyway I can refer to new Waffle() without referring to the actual name of the constructor function meaning so I could copy and paste this each time and not have to change anything. Meaning I could I save Waffle() as a variable and do something like

return new var

I wish I could use this.name but that doesn't work either until it is invoked.

I have a feeling I can't but wanted to at least ask some of the people here on stack overflow if it was a possibility

Again your comments and feedback is appreciated

like image 932
James Daly Avatar asked Jun 10 '13 20:06

James Daly


People also ask

What is new student () in JavaScript?

The new keyword is used in javascript to create a object from a constructor function. The new keyword has to be placed before the constructor function call and will do the following things: Creates a new object. Sets the prototype of this object to the constructor function's prototype property.

Does JavaScript have design patterns?

You may not know it, but you've used a JavaScript design pattern. Design patterns are reusable solutions to commonly occurring problems in software design. During any language's lifespan, many such reusable solutions are made and tested by a large number of developers from that language's community.

How many design patterns are there in JavaScript?

The book explores the capabilities and pitfalls of object-oriented programming, and describes 23 useful patterns that you can implement to solve common programming problems. These patterns are not algorithms or specific implementations.

How does New keyword work in JavaScript?

When a function is called with the new keyword, the function will be used as a constructor. new will do the following things: Creates a blank, plain JavaScript object. For convenience, let's call it newInstance .


1 Answers

I have a better solution. This is what you're currently doing:

function Waffle() {
    if (!(this instanceof Waffle))
        return new Waffle;
    this.tastes = "yummy";
}

Waffle.prototype.wantAnother = true;

This pattern isn't really nice because you're mixing the code to construct a new object with the code to check if the new keyword is being used.

I've mentioned before that you shouldn't use the new keyword in JavaScript as it breaks functional features. Instead let's create another function which does the same thing:

Function.prototype.new = (function () {
    return function () {
        functor.prototype = this.prototype;
        return new functor(this, arguments);
    };

    function functor(constructor, args) {
        return constructor.apply(this, args);
    }
}());

This function allows you to create an instance of a function as follows:

var waffle = Waffle.new();

However we don't want to use new at all. So to do away with it we'll create a function which wraps a constructor as follows:

function constructible(constructor) {
    function functor() { return Function.new.apply(constructor, arguments); }
    functor.prototype = constructor.prototype;
    return functor;
}

Now we can define the Waffle function as follows:

var Waffle = constructible(function () {
    this.tastes = "yummy";
});

Waffle.prototype.wantAnother = true;

Now you can create objects with or without using new:

var first = new Waffle;
var second = Waffle();

Note: The constructible function is pretty slow. Use the following version of constructible instead - it's a little faster:

function constructible(constructor) {
    constructor = Function.bind.bind(constructor, null);
    function functor() { return new (constructor.apply(null, arguments)); }
    functor.prototype = constructor.prototype;
    return functor;
}

Personally I wouldn't use either of these two methods. I would just remember to write new, or (more likely) I would restructure my code as follows:

var waffle = {
    create: function () {
        var waffle = Object.create(this);
        waffle.tastes = "yummy";
        return waffle;
    },
    wantAnother: true
};

var first = waffle.create();
var second = waffle.create();

If you want to know more about this pattern then read the following answer: https://stackoverflow.com/a/17008403/783743

like image 141
Aadit M Shah Avatar answered Sep 30 '22 17:09

Aadit M Shah