Javascript Patterns--读书笔记5 (Object Creation Patterns)

在JS中创建一个对象是非常简单的,可以利用直接量 var object={},也可以用constructor var object = new Object().而且它本身没有特殊的语法,像什么命名空间,modules, packages, private properties和static members.在下面的内容中将会集中展示,命名空间模式,依赖声明,module模式和sandbox模式,它们可以帮助你更好的组织你的代码。

Namespace Pattern

namespace可以帮助我们的程序尽力减少对全局变量的污染,这样我们就可以把命名冲突减小到最低。当然javascript并没有提供原生的支持,就是说并没有像其他语言中直接有声明namespace的语法。不过,我们可以很轻松的来实现它,我们可以声明一个object,然后把所有用到的方法全部加入进来。

View Code
//我们来看如何把5个global,缩成一个



//constructors

function Parent(){}

function Child(){}



var some_var=1;



//some objects

var module1 ={};

module1.data ={a:1, b:2}

var module2={}



//一个global object

var MYAPP = {};



//constructors

MYAPP.Parent = function() {};

MYAPP.Child=function(){};



MYAPP.modules={};

MYAPP.modules.module1={};

MYAPP.modules.module1.data={a:1, b:2};

MYAPP.modules.module2={}

上面的代码展示了如何将5个global varibale变成一个.

上述代码可以很好的来避免了全局变量的冲突,但是还会存在着许多的不足:

  • 名字太长,我们需要键入太多的代码,这意味着会增大文件,从而浪费加载时间
  • 只有一个总的全局变量,这意味着所有的code都可以来更改这个global,而且其它的部分也会得到这些更改过的状态
  • 太长的命名,意味着花更多的时间来查找每个内嵌的变量

sandbox模式可以避免上述缺点.

Declaring Dependencies

javascript库一般是modular和namespaced.这意味着你可以只加载你想要的modules.例如YUI,这里只有一个global的全局变量YAHOO,但是有许多的module,比如DOM Module: YAHOO.util.Dom, Event Module:YAHOO.util.Event

View Code
var myFunction = function(){

  var event = YAHOO.util.Event,

        dom = YAHOO.util.DOM;

}

 尽管上述代码只是很简单的pattern,但是却有很多好处:

  • 可以很清晰的告诉我们你所依赖的script file是否被引用到page当中。
  • 把声明放在前边可以很清晰的发现和解决依赖。
  • 另外,通过这种方式可以提高效率,我们不需要再去一层层的查找了,例如Yahoo.util.dom,我们可以直接用dom来引用,大幅度的提高代码效率。

Private Properties and Methods

在Javascript中object中的所有成员都是public的.

private Members:

我们可以借助于closure来实现private members.

View Code
function Gadget(){

  //private member

  var name = 'iPod';

  //public function

  this.getName = function(){

    return name;

  }

}



var toy = new Gadget();



//'name' is undefined, it's private

console.log(toy.name);//undefined



console.log(toy.getName();//'iPod'

Object Literals and Privacy

View Code
var myobj;//this will be the object

(function(){

  //private members

  var name ="my, oh my";

  

  myobj = {

   getName : function() {

     return name;

   };

  };

}());



myobj.getName();//"my, oh my"

Prototypes and Privacy

View Code
function Gadget(){

  //private members

  var name ='iPod';

  //public function 

  this.getName = function() {

    return name;

  }

}



Gadget.prototype = (function(){

  //private member

  var browser = 'Mobile Webkit';

  return {

    getBrowser: function(){

     return browser;

   }

  }

}());



var toy = new Gadget();

console.log(toy.getName());//privileged "own" method

console.log(toy.getBrowser());//privileged prototype method

 

Module Pattern

module可以给我们提供一种更好的组织代码的方式来面对日益增长的code.来看下面的code,我们首先建立一个namespace,然后定义一个局部变量,然后把我们的那些公共方法以一个object的形式来返回。

View Code
//首先声明一个命名空间

MYAPP.namespace("MYAPP.utilities.array');



//以immediate execute的方式返回一个object

MYAPP.utilities.array = (function(){

    //声明依赖的函数

    var uobj = MYAPP.utilities.object,

        ulang = MYAPP.utilities.lang,

        

        //声明private properties

        array_string = "[objects Array]",

        ops = Object.prototype.toString;

        

        //private methods

        //...

        //返回public API

        return {

            inArray: function(needle, haystack){

                for(var i=0, max = haystack.length; i<max; i+=1){

                    if(haystack[i] === needle){

                      return true;

                    }

                }

            },

            isArray: function(a){

                return ops.call(a) === array_string;

            }

        };

    

}());

用构造函数来创造module的模式

也许有的时候,我们更想要用到构造函数来创造一个新的对象

View Code
//首先声明一个命名空间

MYAPP.namespace("MYAPP.utilities.array');



//以immediate execute的方式返回一个object

MYAPP.utilities.array = (function(){

    //声明依赖的函数

    var uobj = MYAPP.utilities.object,

        ulang = MYAPP.utilities.lang,

        

        //声明private properties

        Constr;

        array_string = "[objects Array]",

        ops = Object.prototype.toString;

        

        //private methods

        //...

        //返回public API

        Constr = function(o){

            this.elements = this.toArray(o);

        }

        

        //public API -- prototype

        Constr.prototype = {

            constructor: MYAPP.utilities.Array,

            version: '2.0',

            toArray: function(obj){

                for(var i=0, a=[], len = obj.length; i<len; i++){

                    a[i] = obj[i];

                }

                return a;

            }

        }

        return Constr;

    

}());

如果我们想要上边的对象,我们可以用var arrObj = new MYAPP.utilities.Array(obj);

 

Sandbox Pattern

sandbox可以解决namesapceing pattern的一些缺点:

  • 在namespacing pattern的时候,我们无法解决一个全局变量来引用同一个库的两个版本的问题,因为它们都会依赖于同一个全局变量
  • 很长的用点分隔的名字,因为那样会降低我们的效率。

如果用sandbox我们以传给它的构造函数一个callback function, 这样的话就相当于我们提供了一个单独封闭的环境给你的code

new Sandbox(function(box){

  your code here.

});

这个模式还需要加入两个feature

  • 我们不需要用new 可以来创造 一个新的对象
  • Sandbox()可以接受另外一个configure object,这个object指示明了我们需要的对象。

就像这样: Sandbox(['ajax','event'], function(box){

  //我们依赖于ajax, event这两个object

});

如何构建Sandbox构造函数:

View Code
//下面新添的两个只是为了对后面的constructor代码起一个帮助的作用,如果想看更好的实现推荐requirejs

Sandbox.modules = {};



Sandbox.modules.dom = function(box) {

    box.getElement = function() {};

    box.getStyle = function() {};

    box.foo = "bar";

}



Sandbox.modules.event = function(box) {    

    box.attacheEvet = function() {};

    box.dettachEvent = function() {};

};



//Implementig the Constructor

function Sandbox(){

    var args = Array.prototype.slice.call(argumentss),//首先把arguments转化为数组,看后面的pop函数

        callback = args.pop(),

        //对于modules,我们可以以一个字符串的形式,也可以传入一个数组。

        modules = (args[0] && typeof args[0] === 'string') ? args : args [0];

        i;//介这是为后边遍历用的

        

        //下面的代码,保证了我们如果不用new,也会返回一个object

        if(!(this instanceof Sandbox)){

            return new Sandbox(modules, callback);

        }

        

        //我们可以加入一些属性,如果有必要

        this.a =1;

        this.b = 2;

        

        //好的我们把一些需要的module加入到this object

        //如果是‘*’或者是没有modules, 我们

        if(!modules || modules ==='*'){

            moduels = [];

            for( i  in Sandbox.moduels){

                if(Sandbox.modules.hasOwnProperty(i)){

                    moduels.push(i);

                }

            }

        }

        

        //初始化这些我们需要的moduels,就是类似于我们可以用this.event, this.dom我们已经在上面的

        for( i=0; i < modules.length; i+=1){

            Sandbox.moduels[moduels[i]](this);

        }

        

        //把this传入到callback中

        callback(this);

}



//添加一些

 

PublicStatic members

View Code
//constructor

var Gadget = function() {};



Gadget.isShiny = function() {

return "you bet";

};



//注意我们只能通过构造函数来调用这个函数

Gadget.isShiny();//you bet

 

Private Static Members

直接看代码

View Code
var Gadget = (function(){

//static varibable/property

var counter = 0;



//returning the new implementation

return function(){

console.log(counter+=1);

}

}());



var g1 = new Gadget();//log1

var g2 = new Gadget();//log2

var g3 = new Gadget();//log3

 

 

 

 

你可能感兴趣的:(JavaScript)