js模式第五章

命名空间模式

命名空间有助于减小程序中所须要的全局变量的数量,而且同事还有助于避免命名冲突或过长的名字前缀。咱们能够建立一个全局对象,将所需的方法,属性添加到这个对象中。避免了变量全局污染。并且一样能避免与第三库的命名冲突。可是一样存在一些缺点:dom

  • 使用的时候,须要附加全局对象这个前缀,增长了不少重复代码。
  • 长嵌套名字意味着更长的属性解析查询时间
  • 一个全局对象意味着,任何部分的代码都能修改这个全局对象,而且影响全部调用该对象的地方。

通用命名空间函数

当咱们往这个全局对象添加一个属性时,可能覆盖以前已经定义的属性了,全部咱们在添加时,先得检测这个添加的属性在这个全局对象中是否已经存在。Code:模块化

var MYAPP={};

if(typeof MYAPP === "undefined"){
    var MYAPP={};
}

var MYAPP = MYAPP || {};
复制代码

这种检测一个对象好使,可是检测链式对象时,显得乏力,代码也会变得臃肿。全部咱们须要设计一个能够检测链式对象的方法。Code:函数

MYAPP.namespace('MYAPP.modules.module2');
复制代码

具体的方法实现。Code:测试

var MYAPP = MYAPP || {};

MYAPP.namespace = function (ns_string){
    var parts = ns_string.split('.'),
        parent = MYAPP,
        i;
    if(parent[0] === "MYAPP"){
        parts = parts.slice(1);
    }

    for(i=0; i < parts.length; i++>){
        if(typeof parts[i] === "undefined"){
            parent[parts[i]]={};
        }
        parent = parent[parts[i]]
    }
    return parent;
};
复制代码

声明依赖关系

在函数或顶部声明代码所依赖的模块是一个很好的方法。由于这种声明仅涉及建立一个局部变量并使其指向所需的模块。Code:this

var myFunction = function (){
    var event = YAHOO.util.Event,
        dom = YAHOO.util.Dom;
};
复制代码

这种模式有以下几个优势:spa

  • 显示的依赖声明代表须要的特定脚本已经包含在该页面中。
  • 在函数顶部的前期声明可使页面维护者很容易地发现并解析依赖。
  • 解析局部变量的速度老是要比解析全局变量(YAHOO)要快,甚至比使用全局变量的嵌套属性(YAHOO.util.Dom)还要快。
  • 将第三方模块赋值给重命名的局部变量,能够拥有更好的代码量,由于咱们可使用更短的局部变量。

私有属性和方法

js中并无特殊的语法来表示私有、保护、或公共属性和方法。由于js中全部对象的成员都是公共的。prototype

好比咱们随便建立一个对象:设计

var obj{
    name:'nei',
    run:function(){
        console.log('Run');
    }
};

obj.name //公共的,能够随便访问的。
复制代码

即便使用构造函数一样如此:code

function Obj(){
    this.name='Nei';
    this.run=function(){
        console.log('run');
    };
}

var o1=new Obj();

o1.name //公共的 能够随便访问的
复制代码

可是有时咱们须要私有成员,因此诞生了下面的这些生成私有成员的方法。对象

私有成员

虽然js自己没有直接建立私有成员的方法,可是咱们将变量控制在函数做用域内,保证外部访问不到它,这样同样能够建立私有成员,好比咱们建立一个类,在类里面建立一个局部变量,而后用公共方法将它暴露出去,这样咱们就能够建立一个私有变量,可是有个公共方法又能够访问到它。

function Nei(){
    var _name='nei';
    this.getName=function(){
        return _name;
    };
}

var n=new Nei();
n.name   //undefined
n.getName() //"nei"
复制代码

模块模式

模块模式就以下几种的集合:

  • 命名空间
  • 即时函数
  • 私有和特权成员
  • 声明依赖

沙箱模式

顾名思义就是提供了一个可用于模块运行的环境,且不会对其余模块和我的沙箱形成任何影响。

全局构造函数

命名空间模式中有一个全局对象,在沙箱模式中,咱们能够设置一个全局构造函数,建立一个隔离的沙箱环境。Code:

new Sandbox(function(box)){
    ....
});
复制代码

经过添加新特征,使这个模式更先进:

  • 经过第三章的强制new模式,能够假设在建立对象是不须要new操做符。
  • 构造函数能够接受一个额外的配置参数(或多个),其中该参数指定了对象实例所须要的模块名。但愿代码是模块化的,所以绝大部分构造函数提供的功能将被限制在模块中。

静态成员

静态成员分为公有静态成员和私有静态成员

公有静态成员

所谓公有就是直接暴露在对象的属性上,外部能够访问。Code:

var Garget=function(){};

//静态方法
Garget.isShiny=function(){
    return "you bet";
};

//普通方法
Garget.prototype.setPrice=function(price){
    this.price=price;
};

//能够直接调用静态方法
Garget.isShiny();//输出 you bet

//普通方法必须建立一个实例,实例调用
var demo1=new Garget();
demo1.setPrice(12);
复制代码

试图以静态方法调用一个实例方法是没法正常运行的。一样,若是使用实例调用静态方法也是没法正常运行的:

typeof Garget.setPrice; // undefined
typeof demo1.isShiny; // undefined
复制代码

若是静态方法也可以被实例调用,只需从新写一个原型方法便可:

Garget.prototype.isShiny=Garget.isShiny;
demo1.isShiny; // 输出 “you bet”
复制代码

可是要注意这里的this指向问题,执行Garget.isShiny时,this指向Garget。执行demo1.isShiny时,this指向demo1。

咱们能够用instanceof肯定方法是如何被调用的:

var Garget=function(price){
     this.price=price
 };

 Garget.isShiny=function(){
     var msg="you bet";

     is(this instanceof Garget){
         msg += ", it costs $"+ this.price + "!";
     }
     return msg;
 };

 Garget.prototype.isShiny=function(){
     return Garget.isShiny.call(this);
 };

 //调用静态方法
 Garget.isShiny; // 输出 "you bet"

 //实例调用
 var d1=new Garget(12);
 d1.isShiny(); // 输出 "you bet,it costs $12!"
复制代码

私有静态成员

私有静态成员具备以下属性:

  • 以同一个函数所建立的全部对象共享该成员
  • 构造函数外部不可访问。

利用当即执行函数实现一个简单的私有静态成员:

var Garget=(function(){
    var counter=0;
    return function(){
        console.log(counter+=1);
    };
})();

//屡次调用
var d1=new Garget(); // 1
var d2=new Garget(); // 2
var d3=new Garget(); // 3
复制代码

如今,咱们经过一个特权方法将私有属性暴露出去:

var Garget=(function(){
    var counter=0,
        NewGarget;

    NewGarget=function(){
        counter+=1;
    };

    //私有特权方法
    NewGarget.prototype.getLastId=function(){
        return counter;
    };

    //重写构造函数
    return NewGarget;
})();

//测试
var d1=new Garget();
d1.getLastId(); // 1
var d2=new Garget();
d2.getLastId(); // 2
var d3=new Garget();
d3.getLastId(); // 3
复制代码

静态属性能够包含非实例相关的方法和数据,而且不会为每一个实例从新建立静态属性。

链模式

链模式最重要的一个要点,须要显示返回的this对象。

相关文章
相关标签/搜索