Notes of Maks Nemisj

Experiments with JavaScript

JavaScript without “new” and “this”keywords

“If you don’t like ‘this’, try Zet.js” (c) M.Nemisj

Plot: This article is about an experiment of avoiding “this” and “new” keywords in JavaScript and about the results of it.

Harmful “new” keyword and replacement for that

There are different debates flying around the internet about the safety of using “new” keyword in JavaScript. It’s all started when Douglas Crockford stated that “new” keyword can be harmful and that he doesn’t use it any more in his code. In replacement for that Douglas Crockford proposed factory functions. In public they also called sometimes Function OOP or Module pattern.

I really like dynamic nature of JavaScript, so this solution excited me. The fact that in JavaScript there is always something new to found or new to learn brings me esteem to the JavaScript language.

The only thing which I considered to be not elegant in this solution, was the inheritance paradigm. It gave me the feeling that code is too “custom”, too “hardcoded”. To fully understand what I mean, you should see it yourself:

This is how normal factory function looks like :

var User = function(){
    var privatMethod = function(){
        alert('hello');
    }

    return {
        sayHello : function(){
            privateMethod();
            this.done = true;
        }
    }
}

In the code above we created declaration of the User class.

Creation of the new User instance is possible without “new” keyword:

var user1 = User();
var user2 = User();

Now, let’s imagine that we would like to create sub-class of the User. Using inheritance in this pattern is not trivial when it concerns methods overriding, but it still can be achieved by the following code:

var SubUser = function(){
    var user = User();
    var oldMethod = user.sayHello;

    user.sayHello = function(){
        oldMethod.apply(user, arguments);
        user.done = false;
    }

    return user;
}

As you can see, the declaration of subclass differs from its super-class. In my opinion this makes code less readable, and more fragile. Moreover there is too much logic involved inside the declaration of the class itself( like “apply” logic or keeping track of instance scope), so code does not become self-expressing to the reader.

That’s why my idea was to make library which would make some unified structure for Class declaration in Functional OOP style with inheritance support. There are some libraries which support Functional OOP style, but all of them, which I’ve seen are using “new” keyword. Then I’ve started with experiments and ended up with the library which is full of experiments or simply Zet.js. About all of the interesting points and experiments you can read bellow in this post.

First seeing, then believing

Before reading all this text bellow, I guess it can be interesting to see how class declaration with Zet.js looks like. Let’s redeclare SubUser :

Zet.declare('SubUser', {
    superclass : User,
    defineBody : function(that){
        Zet.public({
            sayHello : function(){
                that.inherited(arguments);
                that.done = false;
            }
        });
    }
});

Scope substitution & why no “this” usage.

Working with different people, reading articles on the net, brings me to the idea, that “this” keyword is one of the most complex concepts in the JavaScript. Especially when new developers find out that “this” can point to different scopes. Such instability of “this” keyword brings a lot of confusion, especially to the people, who came from static languages like Java or C#.

First and most valuable aspect of Zet.js is, that it provides a solution to stop dealing with cumbersome “this” variable.

There are different ways in which “this” variable can be substituted. I think, it’s essential to know global/important cases, when it can occur. People, who are not interested in causalities can skip this chapter and start reading about implementation details.

As I told, by knowing most used cases it’s much more easier to identify the generic solution. One of the most important cases in my list is accessing of “this” variable from within anonymous function. Let’s look at standard non working example below.

User.prototype.delayMe = function(){
    setTimeout(function(){
        this.someFunction();
    },100);
}

Since “this” variable inside anonymous function points to the global scope, the code will throw error, because someFunction is undefined. I guess, this situation happened to most of us, including me. At the time when I only started with JavaScript, my attempt to fix this was to assign function to the variable and then execute it.

User.prototype.delayMe = function(){
    var someFunction = this.someFunction;
    setTimeout(function(){
        someFunction();
    },100);
}

Perhaps, code looks logic and normal, and in some situations it may work, but it’s still not working code. The problem is that as soon as someFunction will try to access “this” variable inside of it, code will break. The reason stays the same. Function someFunction is called as anonymous, so “this” variable will point to the global scope.

To help JavaScript developers, most frameworks and libraries offers helping functions, like “bind” in jQuery or “hitch” in Dojo to use. They help to keep correct scope at the moment of the execution.

User.prototype.delayMe = function(){
   var someFunction = dojo.hitch(this,'someFunction');
    setTimeout(function(){
        someFunction();
    },100);
}

Although we have now support from libraries, there are another two cases which can lead to scope substitution. Take notice that one of them is only valid, if instances are created with “new” keyword.

1. Instantiate class without *"new"* keyword.
2. Using apply or call API calls

I will not explain first one, since the Functional OOP prevents this kind of bugs by default, but let’s check the second one.

Intentionally substitute scope can be done through call or apply API calls. By using one of this it’s possible to make “this” aim at any JavaScript object. In some situations this can be useful (hitch and bind are based on this), but also it can lead to unpredictable results.

After all this theory material it’s time to see what Zet.js proposes.

Protecting “this” with *”that”

To protect “this” variable from pointing it to some-where-we-do-not-know, Zet.js prevents usage of it. Instead Zet.js forces developers to use “that” variable. This variable is available from the begin of the instance life-cycle and always points to the correct scope.

JavaScript developers knows, that “this” variable can be assigned to anything (caching it). Zet.js passes “that” to the factory function at the moment of execution and it stays in the private scope of the instance. Because private scope is always available to the body of the instance, developer always have the correct value of “this” in hands.

I also want to notice that, by having such manner of declaring classes, all the private functions inside the class also automatically have the scope to the object instance. This means, that there is no more need in doing extra work like privateFunction.call(this); to access public variables or functions from the private scope.

Let’s look at the example one more time.

Zet.declare('SubUser', {
    superclass : User,
    defineBody : function(that){
        Zet.public({
            sayHello : function(){
                that.inherited(arguments);
                that.done = false;
            }
        });
    }
});

As I mentioned already class declarator passes “that” to defineBody factory function, which points already to newly created object.

Strange Zet.public function

I guess you’ve already noticed strange Zet.public declaration in defineBody factory. This is another experiment of mine. It is not usual to see such way of declaring things, but it is made to create logical split between functions, which are included for private purpose and public functions. Further it brings totally no functionality into the object, pure for experiment.

In case you think, this is REALLY useless, Zet.js supports also return statement as normal Functional OOP declaration does.

Zet.declare('SubUser', {
    superclass : User,
    defineBody : function(that){
        return {
            sayHello : function(){
                that.inherited(arguments);
                that.done = false;
        };
    }
});

Moreover Zet.js also supports style for developers who has been used to the functional style in “normal” JavaScript Classes:

Zet.declare('SubUser', {
superclass : User,
defineBody : function(that){
that.sayHello = function(){
that.inherited(arguments);
that.done = false;
}
}
});

Except that in such situation “that” variable should be used instead of “this”.

Functional OOP/Module pattern pitfall.

One of the strong arguments for people not to use Functional OOP is the fact that the instanceof functionality is not working correctly. Because factory function creates every time unique object instanceof will always return false.

I’ve seen some solutions to fix this, but they remain using “new” keyword internally in the declarator itself. As I told already before, Zet.js is truly “newless”, so I could not use any of the solutions which I’ve seen.

Instead Zet.js extend every instance of the object with own instanceOf method. Passing class constructor to this function will return false or true depending on the constructor which belongs to this object or to its superclass. Thus, expressions bellow will return true.

subUser1.instanceOf(User);
subUser1.instanceOf(SubUser);

To make instanceOf more universal, I’ve included global instanceOf method API. Which works with normal objects, Zet objects and with fixed instanceof String case :

// Zet instances:
Zet(User).instanceOf(User) //return true;
Zet(subUser1).instanceOf(User) //return true;

// normal instance
Zet([]).instanceOf(Array) // return true;

// String instanceof fix
"some-string" instanceof String //return false
Zet("some-string").instanceOf(String); // return true

instanceOf method of Zet.js can be also used as a drop-in-replacement for native instanceof function.

Is there something normal in Zet.js?

Yes, besides strange .public syntax, forced “that” usage and other experimental stuff, Zet.js also has some “normal” facilities, like :

  • Support for Inheritance
  • Separate “initialize” call
  • Declaring classes through Namespaces
  • Simple loggin facilities
  • Inner constructor function
  • CommonJS Modules API support

This article is big enough, so I will not describe here in details  all of the listed things. If you are interested you can find all the explanation inside README on a github.

Update : As noted by Tim Caswell it’s better to name your factory functions with a “new” prefix to indicate that such constructor should be called without new keyword, for example :

var person = newPerson();

Also it’s important to understand that each instance of such factory has a big impact on the memory, since it consists of own copy of all the functions of the class.

Zet.log("That's all");

Download zet.js in a zip


, , , , ,

22 thoughts on “JavaScript without “new” and “this”keywords

  • Matt Parlane says:

    Not a bad idea… one bit of feedback though:

    I’m not sure I like the use of the word “that” – how about “my”? It makes more sense to me, and also Perl developers would feel right at home.

    Picky I know, but I think it fits nicely.

  • […] from javascript. Is it really necessary? Feb 11 Javascript, Languages, OO Maks Nemisj has a very interesting article about removing 2 keywords (‘new’ and ‘this’) from Javascript to make OOP […]

  • Maks Nemisj says:

    @Matt Parlane :

    Thanks for your feedback. Actually, It’s all up to you, how you call the reference to “this” keyword. You can call it “my”( Perl style) or “self” (Python style ) or “zis” ( Your own style).

    Zet.declare('Class', {
        defineBody : function(my){
            that.sayHello = function(){
                my.inherited(arguments);
            }
        }
    });

    But it’s a good point, thanks.

  • I like the declarative nature of it. I’ll give the code a try and see.

    As to your advice about using “my”, “self”, or “zis”, I agree with you that it can be anything, however, I don’t think “self” is a good choice. window.self (or just self) is already something (https://developer.mozilla.org/En/DOM/Window.self). You would be shadowing that variable. More than likely, that isn’t an issue as you will rarely need “self”, but just to be a good citizen 🙂

  • Zecc says:

    Just in case someone needs it, here’s the direct URL to Crockford’s post:
    http://javascript.crockford.com/prototypal.html

  • Maks Nemisj says:

    @Zecc:

    Are you sure you wanted to link to “prototypal” page and not to this one http://javascript.crockford.com/private.html ?

  • SM says:

    Great article. Thanks

  • […] JavaScript without “new” and “this”keywords […]

  • mavi koltuk says:

    I’d love to see a follow up on this.

  • […] JavaScript without “new” and “this”keywords […]

  • Just one small point.

    When using those kinds of factory functions that create objects without the need of the ‘new’ keyword, you should ideally name them using camelCase rather than PascalCase.

    So in your example, it would be like such:

    var user = function(){ …

    var user1 = user();

    This is because capitalized function names are usually used to indicate that the function is a constructor and thus needs the ‘new’ keyword for invocation. Since JavaScript does not signal any form of warning when not using the ‘new’ keyword in places where it should have been used, using capitalized names is a way for such an indication.

  • Maks Nemisj says:

    @Andreas Grech:

    Make sense. But I will explain you my thoughts about camelCase and PascalCase.

    Usually you are not using more then one factory inside your app/framework/lib. Also as soon as you start using one of them you try to stick to it, and to declare everything at the same way. First of all it keeps your code consistent and also it minimizes “the places, where it can go wrong”. That’s why I assume that in such code you will not see the mixing of different declarations, like “var user = User()” and “var thing = new Thing()”. This means, that you will not have to think “Should I use ‘new’ or without ‘new’ for this class” ?

    Further I think that the person who was putting the basics for the app/framework/lib has consciously chosen such factory and he is the one, who is responsible for brining that info to others who are going to use it.

    At the moment when you try to use camelCase for classes without “new”, you leave yourself completely without no awareness to distinguish the classes from the functions. Switching to another factory or library at a later moment can become much harder, since you can’t do it anymore based on the pattern like “=\s*[A-Z][^(]*\(” ( so “sed” or any other search and replace tooling will be of no use ). In this case you will have to do it manually or use some other more complex tricks.

    For me personally, it’s important that the code at which I look, is expressive enough or at least has some hits. And this is exactly what code “var user = User()” is doing for me. It shows me “Hey, there is a function call, but no new. Hm, it starts with capital letter, why is that?”

  • I agree that you should keep code consistent across your code base, but what if you are using more than a single library? What if there is more than developer working on the same library?

    In that case, I presume that it’s not an uncommon sight to see ‘var p = new Person();’ and ‘var u = user();’ in your code. That’s why I suggested that you should keep to this well-known convention.

    JavaScript is already a very messy language as it is…people mixing conventions will not help improving this mess.

    Also, you said it yourself: “Should I use ‘new’ or without ‘new’ for this class”.
    By keeping to a common, well-known convention, you can overcome this obstacle. Therefore, if a user sees that a function starts with a Capital letter, he knows that it must be invoked with the ‘new’ keyword.

    As regards your last paragraph, I can’t really understand your point there. So you’re saying that it’s a good thing that a user is confused as to whether to use the ‘new’ keyword or not (“Hey, there is a function call, but no new. Hm, it starts with capital letter, why is that?”)? Why violate the Principle of least astonishment like that?

  • Maks Nemisj says:

    @Andreas Grech

    I think your first paragraph is exactly the place where our thoughts are going separate ways. The fundamental difference in views, at which we ground our arguments, pros and cons.

    As I said, my main idea is that choosing only one factory and using the same conventions everywhere for the whole codebase is just a “MUST”. It shouldn’t matter “if there is more than developer working on the same library”. This is the reasons why I do not see “an uncommon sight to see ‘var p = new Person();’ and ‘var u = user();’” in the code. Having such mixin in your code, means that conventions are not used. And if such developers unable to stick to one format in their own code, how do you want them to stick to the global well-known conventions for the whole JavaScript?

    Of course, you are totally right that we should stick to the common and well-known conventions, personally I think that too. The only reason I used PascalCase naming is to make the clear separation between Classes and function calls. In the case when more than one library is used, indeed, it might be better to use lowercase names for factory classes.

  • Tim Caswell says:

    @Maks

    This is an excellent article explaining the pros of the factory pattern to simulate “classes”. I just have a couple notes.

    First, if you do ever mix constructor functions with factory functions, then you can prefix your factory function names with new. For example, let’s assume I have two “classes” Person and Shape. Person is implemented using a constructor and Shape is implemented using a factory.

    function Person(…) {…}
    Person.prototype.foo = …

    function newShape(…) {
    return …
    }

    Then when you’re using them, it will be either “new Person()” or “newShape()”

    Secondly, I am a huge personal fan of the factory style for creating objects, but it’s unfair to promote it without warning people of the performance costs. Each and every instance has it’s own copy of every function and a closure for each. This comes as a huge cost if you’re going to be making lots of these.

    Anyway, overall a great article.

  • Maks Nemisj says:

    @Tim Caswell

    Thanks for your enthusiastic comment.

    I think your idea with a “newClass” prefix is really great. It gives the compromised solution for our last discussion with Andreas Grech. It starts with small letter and it gives precise indication of the Class. Really nice.

    Talking about performance warning, you are completely right. I will add it as the footnote to the article, together with advices of “new” prefix.

  • Wouldn’t it be better to just define SubUser like this?

    “`js
    var SubUser = function() {
    var subUser = {};

    var user = User();

    subUser.sayHello = function() {
    user.sayHello();
    subUser.done = false;
    };

    return subUser;
    };
    “`

    I’ve always felt that replacing `this` with closures and replacing inheritance with composition have to be done together. If you want inheritance, then you either need to keep using `this` or use a library like the one you’ve created, but we’re better off with composition anyway.

  • Lee says:

    Great article! this and new considered harmful!

    I writ an article about more of their pitfalls and suggested another way of writing js without the need for a library http://how.nz/2015/07/24/javascript-this-new-and-object-oriented-programming/

    Zet looks interesting and reminds me of Pythons explicit handling of self which i like.

    I admittedly didn’t consider instanceof while writing that, it turns out my method of writing JS doesnt support it but i don’t use it anyway and prefer the more flexible method of duck typing (does it have said methods and properties rather than is it of a specific type)

    unfortunately for us ES6 classes use this and new which will lead to tonnes of people with more problems with this loosing scope and new which locks us into a function call being a specific type of object creation which makes it harder to change code to use factories and get rid of this once and forall!

    Great article thanks again.

  • Maks Nemisj says:

    @Andrew Morris,

    Yeah, sure, you can define it like this also, but that’s the whole point of my library to eliminate boilerplate code, like creating User instance, creating reference to original method, etc. It’s the matter of eliminating all this and abstracting it away.

  • Maks Nemisj says:

    @Lee,

    You’re welcome.
    Regarding ES6/es2015 they’ve at least have standardized the way ihretitance should work and introduced the ‘super’ keyword. I have to say that because ES6 has now arrow functions, I think it will help people eliminate problems with incorrectly bound context.

  • […] I wouldn’t go that far, but if you’re interested in the topic, there’s a nice article exploring how to avoid using this and new. However, keep in mind that the article has been written before fat arrow functions become widely […]

  • Damiano Falcioni says:

    @Tim Caswell
    @Marks

    The performance issues are not a problem if you structure your common functions in a closure, simulating so the prototype behaviour. Like this:

    var newModule = (function(){
        //put here all the private variables or functions common to all the module 'instances', aka functions that you do not want to be duplicated on every instantiation (like the functions inside prototype)
        
        return function() {
            //put here all the private variables or functions common to a specific module 'instances', aka functions and variables that have to be duplicated and initialized on every instantiation
            
            return {
                //put here the public module variables or functions that this module will return
            	}
            };
        };
    }());
    
    var myModule = newModule();
    

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.