Search code examples
javascriptclosurespolyfillsiife

polyfill of javascript Object create with simple form


The polyfill of javascript Object.create(), by some codes in which I am totally confused. The code link is polyfill of Object create.

if (typeof Object.create != 'function') {
    // Production steps of ECMA-262, Edition 5, 15.2.3.5
    // Reference: http://es5.github.io/#x15.2.3.5
    Object.create = (function() {
        // To save on memory, use a shared constructor
        function Temp() {}

        // make a safe reference to Object.prototype.hasOwnProperty
        var hasOwn = Object.prototype.hasOwnProperty;

        return function(O) {
            // 1. If Type(O) is not Object or Null throw a TypeError exception.
            if (typeof O != 'object') {
                throw TypeError('Object prototype may only be an Object or null');
            }

            // 2. Let obj be the result of creating a new object as if by the
            //    expression new Object() where Object is the standard built-in
            //    constructor with that name
            // 3. Set the [[Prototype]] internal property of obj to O.
            Temp.prototype = O;
            var obj = new Temp();
            Temp.prototype = null; // Let's not keep a stray reference to O...

            // 4. If the argument Properties is present and not undefined, add
            //    own properties to obj as if by calling the standard built-in
            //    function Object.defineProperties with arguments obj and
            //    Properties.
            if (arguments.length > 1) {
                // Object.defineProperties does ToObject on its first argument.
                var Properties = Object(arguments[1]);
                for (var prop in Properties) {
                    if (hasOwn.call(Properties, prop)) {
                        obj[prop] = Properties[prop];
                    }
                }
            }

            // 5. Return obj
            return obj;
        };
    })();
}

  1. Why does it complicate the logic by using IIFE(Immediately Invoked Function Express) and a return function, and closure.
  2. Instead, can I use the simple logic and code below? Is there any wrong or inappropriate content in it? There isn't IIFE and a return function.

if (typeof Object.createOwn != "function") {
    Object.createOwn = function(O) {
        // 1. if Type(O) is not Object or Null throw a TypeError exception.
        if (typeof(O) != "object") {
            throw TypeError("Object prototype may only be an Object or null");
        }

        // 2. Let obj be the result of creating a new object as if by the
        //    expression new Object() where Object is the standard built-in
        //    constructor with that name
        // 3. Set the [[Prototype]] internal property of obj to O.
        var obj;
        var Temp = function() {};
        Temp.prototype = O;
        obj = new Temp();

        // 4. If the argument Properties is present and not undefined, add
        //    own properties to obj as if by calling the standard built-in
        //    function Object.defineProperties with arguments obj and Properties
        if (arguments.length > 1) {
            var Properties = Object(arguments[1]);
            for (var prop in Properties) {
                if (Properties.hasOwnProperty(prop)) {
                    obj[prop] = Properties[prop];
                }
            }
        }
        return obj;
    }
}

var foo = {
    one: 1,
    two: 2
};

var bar = Object.createOwn(foo, 3);


Solution

  • They will both work, but the original is using IIFE for a few reasons. Two of them is mentioned in the comments

    // To save on memory, use a shared constructor
    

    This is not the case with your version, where var Temp = function() {}; is wrapped into the function and a new instance is created every time you use it.

    // make a safe reference to Object.prototype.hasOwnProperty
    

    Since Object.prototype.hasOwnProperty could potentially be overridden for when it's time to use it, the polyfill makes sure it has it's own safe reference to it at each Object.create.

    Then it's also the common reason many use IIFE, to avoid polluting the global namespace.

    These are mostly safeguards, and not required in this case. But I see no reason to remove them.