An in depth understanding of the JavaScript series (47) : object creation patterns (part 1)

  • 2020-05-10 17:45:16
  • OfStack

introduce

This article focuses on patterns for creating objects, using techniques that can greatly avoid errors or allow you to write very lean code.

Pattern 1: namespace (namespace)

Namespaces can reduce the number of global names needed to avoid naming conflicts or excesses. 1. When we define object hierarchy, it is usually like this:


var app = app || {};
app.moduleA = app.moduleA || {};
app.moduleA.subModule = app.moduleA.subModule || {};
app.moduleA.subModule.MethodA = function () {
    console.log("print A");
};
app.moduleA.subModule.MethodB = function () {
    console.log("print B");
};

If you have a lot of layers, you have to keep going like this. It's very confusing. namespace mode is designed to solve this problem. Let's look at the code:

// It is not safe and may overwrite the existing one MYAPP object
var MYAPP = {};
// ok
if (typeof MYAPP === "undefined") {
    var MYAPP = {};
}
// A more concise way
var MYAPP = MYAPP || {}; // Defining generic methods
MYAPP.namespace = function (ns_string) {
    var parts = ns_string.split('.'),
        parent = MYAPP,
        i;     // Default if no 1 A node is MYAPP If so, ignore it, for example MYAPP.ModuleA
    if (parts[0] === "MYAPP") {
        parts = parts.slice(1);
    }     for (i = 0; i < parts.length; i += 1) {
        // If the property does not exist, it is created
        if (typeof parent[parts[i]] === "undefined") {
            parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
};

The calling code is very simple:

// through namespace Later, you can assign the return value to 1 Local variables
var module2 = MYAPP.namespace('MYAPP.modules.module2');
console.log(module2 === MYAPP.modules.module2); // true // skip MYAPP
MYAPP.namespace('modules.module51'); // Very long name
MYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');

Pattern 2: define dependencies

Sometimes one of your modules or functions may refer to a third module or tool. It is best to define the dependencies at the beginning so that they can be easily replaced later.


var myFunction = function () {
    // Rely on the module
    var event = YAHOO.util.Event,
        dom = YAHOO.util.dom;     // Local variables are used in the code that follows other functions event and dom
};

Pattern 3: private properties and private methods

The JavaScript book does not provide a specific syntax to support private properties and private methods, but we can do this with closures, as follows:


function Gadget() {
    // Private objects
    var name = 'iPod';
    // The public function
    this.getName = function () {
        return name;
    };
}
var toy = new Gadget(); // name Undefined, private
console.log(toy.name); // undefined // Public method access name
console.log(toy.getName()); // "iPod" var myobj; // Give through the self-executing function myobj The assignment
(function () {
    // Free object
    var name = "my, oh my";     // It implements the public part, so it doesn't var
    myobj = {
        // Authorization method
        getName: function () {
            return name;
        }
    };
} ());

Mode 4: Revelation mode

It is also about hiding private methods, similar to the Module pattern in the JavaScript series (3) : fully parsing the Module pattern, but instead of declaring a variable externally and assigning it a public method internally. The code is as follows:


var myarray; (function () {
    var astr = "[object Array]",
        toString = Object.prototype.toString;     function isArray(a) {
        return toString.call(a) === astr;
    }     function indexOf(haystack, needle) {
        var i = 0,
            max = haystack.length;
        for (; i < max; i += 1) {
            if (haystack[i] === needle) {
                return i;
            }
        }
        return -1;
    }     // All the above details are hidden by assignment
    myarray = {
        isArray: isArray,
        indexOf: indexOf,
        inArray: indexOf
    };
} ()); // The test code
console.log(myarray.isArray([1, 2])); // true
console.log(myarray.isArray({ 0: 1 })); // false
console.log(myarray.indexOf(["a", "b", "z"], "z")); // 2
console.log(myarray.inArray(["a", "b", "z"], "z")); // 2 myarray.indexOf = null;
console.log(myarray.inArray(["a", "b", "z"], "z")); // 2

Pattern 5: chain pattern

Chain mode allows you to call methods of one object in a row, such as obj.add (1).remove (2).delete (4).add (2). The idea is very simple, which is to return this as it is. The code is as follows:


var obj = {
    value: 1,
    increment: function () {
        this.value += 1;
        return this;
    },
    add: function (v) {
        this.value += v;
        return this;
    },
    shout: function () {
        console.log(this.value);
    }
}; // Chain method call
obj.increment().add(3).shout(); // 5 // You can do it alone 1 a 1 A call
obj.increment();
obj.add(3);
obj.shout();

conclusion

This is the first part of the object creation pattern, so stay tuned for the next part tomorrow.


Related articles: