命名空间有助于减小程序中所须要的全局变量的数量,而且同事还有助于避免命名冲突或过长的名字前缀。咱们能够建立一个全局对象,将所需的方法,属性添加到这个对象中。避免了变量全局污染。并且一样能避免与第三库的命名冲突。可是一样存在一些缺点: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
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)){
....
});
复制代码
经过添加新特征,使这个模式更先进:
静态成员分为公有静态成员和私有静态成员
所谓公有就是直接暴露在对象的属性上,外部能够访问。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对象。