1

I've just discovered that Magento 2's UI Component javascript constructor functions are built in such a way that they (seem to?) behave the same with, and without, the new keyword;

UiElement = requirejs('uiElement');

//both instantiate a new object
object = new UiElement;
object = UiElement():

However, the UI Component registering code

#File: vendor/magento//magento2-base/lib/web/mage/layout.js
function initComponent(node, Constr) {    
    var component = new Constr(_.omit(node, 'children'));

    registry.set(node.name, component);
}

appears to use the new keyword when instantiating these objects.

Does anyone know if there's a downside to not using the new keyword? The object system seems to have been designed such that you can use these constructor functions either way. However, without any core example or solid documentation on the topic, it leaves me wondering if this second, new-less syntax is safe to use.

Hoping someone here knows the answer or can pass me on to someone who does.

2 Answers 2

1

I think the answer lies in UiClass which UiElement extends from: \vendor\magento\module-ui\view\base\web\js\lib\core\class.js.

/**
 * Creates constructor function which allows
 * initialization without usage of a 'new' operator.
 *
 * @param {Object} protoProps - Prototypal propeties of a new consturctor.
 * @param {Function} consturctor
 * @returns {Function} Created consturctor.
 */
function createConstructor(protoProps, consturctor) {
    var UiClass = consturctor;

    if (!UiClass) {

        /**
         * Default constructor function.
         */
        UiClass = function () {
            var obj = this;

            if (!_.isObject(obj) || Object.getPrototypeOf(obj) !== UiClass.prototype) {
                obj = Object.create(UiClass.prototype);
            }

            obj.initialize.apply(obj, arguments);

            return obj;
        };
    }

    UiClass.prototype = protoProps;
    UiClass.prototype.constructor = UiClass;

    return UiClass;
}

It appears that this code enables the object to be initialized with or without new, giving the same result either way.

1
  • +1 for useful information, and yes, that's the function that implements this behavior. However, it's not clear if this function covers all possible edge cases, and since I can't find an example of the non-new instantiation anywhere in Magento core it leads to a suspicion that the not-new syntax might not work across the board. Commented Dec 6, 2016 at 18:14
0

Alright, I came came across this today

UiClass = requirejs('uiClass');
OurClass = UiClass.extend({
    'constructor':function(){
        this.foo = 'baz';
    }
});

object = OurClass(); //won't work because we provided a custom 
                     //constructor that won't build its own object

It turns out the inheritance features of uiClass objects allow you to provide a new constructor function. If you do this, and don't write your constructor function in a very specific way, you'll break the new-less feature of Magento's javascript objects.

So, when you're writing code that's dealing with other people's objects, (as Magento is in the layout.js file, it's probably best to not rely on this new-less feature. It's possible you might have an objects where someone's configured a constructor function. This also means it's probably best to always use new when creating new objects for consistency's sake, and treat the new-less feature as a net that will catch you if you fall.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.