javascript patterns CHAPTER 5 Object Creation Patterns

Creating objects in JavaScript is easy—you either use the object literal or you use constructor functions. In this chapter we go beyond that and see some additional patterns

for object creation.

The JavaScript language is simple and straightforward and often there’s no special syntax for features you may be used to in other languages, such as namespaces, modules,packages, private properties, and static members. This chapter takes you through common patterns to implement, substitute, or just think differently about those features.

We take a look at namespacing, dependency declaration, module pattern, and sandbox patterns—they help you organize and structure your application code and mitigate the
effect of the implied globals. Other topics of discussion include private and privileged members, static and private static members, object constants, chaining, and one class-
inspired way to define constructors.

Namespace Pattern

Namespaces help reduce the number of globals required by our programs and at the same time also help avoid naming collisions or excessive name prefixing.
Consider the following example:

    // BEFORE: 5 globals
    // Warning: antipattern
    // constructors
    function Parent() {}
    function Child() {}
    // a variable
    var some_var = 1;
    // some objects
    var module1 = {};
    module1.data = {a: 1, b: 2};
    var module2 = {};

You can refactor this type of code by creating a single global object for your application,called,  for  example,  MYAPP,  and  change  all  your  functions  and  variables  to  become properties of your global object:
    // AFTER: 1 global
    // global object
    var MYAPP = {};
    // constructors
    MYAPP.Parent = function () {};
    MYAPP.Child = function () {};
    // a variable
    MYAPP.some_var = 1;
    // an object container
    MYAPP.modules = {};
    // nested objects
    MYAPP.modules.module1 = {};
    MYAPP.modules.module1.data = {a: 1, b: 2};
    MYAPP.modules.module2 = {};

For the name of the global namespace object, you can pick, for example, the name of your application or library, your domain name, or your company name. Often developers use the convention of making the global variable ALL CAPS, so it stands out to the readers of the code. (But keep in mind that all caps are also often used for constants.)
This pattern is a good way to namespace your code and to avoid naming collisions in your own code, and collisions between your code and third-party code on the same
page, such as JavaScript libraries or widgets. This pattern is highly recommended and perfectly applicable for many tasks, but it does have some drawbacks:
• A bit more to type; prefixing every variable and function does add up in the total amount of code that needs to be downloaded
• Only one global instance means that any part of the code can modify the global instance and the rest of the functionality gets the updated state
• Long nested names mean longer (slower) property resolution lookups
The sandbox pattern discussed later in the chapter addresses these drawbacks.

General Purpose Namespace Function

As the complexity of a program grows and some parts of code get split into different files and included conditionally, it becomes unsafe to just assume that your code is the first to define a certain namespace or a property  inside of  it. Some of the properties you’re adding to the namespace may already exist, and you could be overwriting them.Therefore before adding a property or creating a namespace, it’s best to check first that it doesn’t already exist, as shown in this example:
    // unsafe
    var MYAPP = {};
    // better
    if (typeof MYAPP === "undefined") {
        var MYAPP = {};
    }
    // or shorter
    var MYAPP = MYAPP || {};

You can see how these added checks can quickly result in a lot of repeating code. For example,  if  you  want  to  define  MYAPP.modules.module2,  you’ll  have  to make  three checks, one for each object or property you’re defining. That’s why it’s handy to have a reusable function that takes care of the namespacing details. Let’s call this function namespace() and use it like so:
    // using a namespace function
    MYAPP.namespace('MYAPP.modules.module2');
    // equivalent to:
    // var MYAPP = {
    //     modules: {
    //         module2: {}
    //     }
    // };

Next is an example implementation of the namespacing function. This implementation is nondestructive, meaning that if a namespace exists, it won’t be re-created:
    var MYAPP = MYAPP || {};
    MYAPP.namespace = function (ns_string) {
        var parts = ns_string.split('.'),
                parent = MYAPP,
                i;
        // strip redundant leading global
        if (parts[0] === "MYAPP") {
            parts = parts.slice(1);
        }
        for (i = 0; i < parts.length; i += 1) {
            // create a property if it doesn't exist
            if (typeof parent[parts[i]] === "undefined") {
                parent[parts[i]] = {};
            }
            parent = parent[parts[i]];
        }
        return parent;
    };

This implementation enables all of these uses:
    // assign returned value to a local var
    var module2 = MYAPP.namespace('MYAPP.modules.module2');
    module2 === MYAPP.modules.module2; // true
    // skip initial `MYAPP`
    MYAPP.namespace('modules.module51');
    // long namespace
    MYAPP.namespace('once.upon.a.time.there.was.this.long.nested.property');

Figure 5-1 shows how  the namespaces  in  the preceding example  look  like when  inspected in Firebug.

Declaring Dependencies

JavaScript libraries are often modular and namespaced, which enables you to include only the modules you require. For example,  in YUI2 there’s a global variable YAHOO,which serves as a namespace, and then modules that are properties of the global variable,  such  as  YAHOO.util.Dom  (the  DOM  module)  and  YAHOO.util.Event  (Events module).
It’s a good idea to declare the modules your code relies on at the top of your function or module. The declaration involves creating only a local variable and pointing to the
desired module:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值