目标:深入了解javascript的私有作用域
实现方式:代码及相关文字解释。
私有作用域:
私有作用域:
window.onload = function(){
var str ='javascript';
(function(){
alert(str);
var str = 'hello world';
alert(str);//hello world
})();
alert(str);//javascript
}
这个例子就很清楚的表明了私有作用域的好处,跟外界的变量方法毫不冲突,豪无关系,没有闭包问题。关于这种语法的解析:
(function(){
//块级作用域
})();
我们都知道这样是可行的:
var fun = function(){
}
fun();
这里我们定义了一个方法后直接调用了,根据上面的代码我们可以变形成:
fun() = function(){}();
然后我们删除没什么用的fun();就得到:
function(){}();
有应为如果这么写,javascript开始解析的时候发现function就把他当做function来解析,发现后面带了一个括号,所以不符合函数的规范报错了,因此将括号包起来就不会报错了。换种方式理解,我们加括号是想让解析器将这个私有作用域前半部分当做方法解析,然后后面加括号直接调用。
还有一种方式也可以自执行那就是赋值,但是对于我们这里是没什么必要的:
var fun = function(){}();
var fun = (function(){})();//谢谢PainsOnline的提醒,写成这样也可以的,也更加方便理解。
私有变量:
function Person(){ function myName(){ return 'fanlizhi'; } this.showName = function(){ alert(myName()); } } var people = new Person(); people.showName();我们在外部是访问不到name的,只能调用自己的showName方法才能访问到内部的myName方法。这只是一个解释私有变量的例子,我们用得更多的会是这样的:
这个例子就很好的阐明了私有变量的好处,以及常用的方式。目的是让私有的变量不能被外部访问到,只能有特定的方法调用。如此一来我们有发现问题了,这里的参数name都是每一个实例单独拥有的,我如果想得到一个所有实例共享的私有变量呢?如果你有java或者其他面向对象语言的基础的话,你会发现我们要的其实就是静态私有变量,没有这些基础也没关系,你了解他的用途也是一样的,我们看下面的一段代码:function Person(name){ this.setName = function(value){ name = value; } this.getName = function(){ return name; } } var people = new Person('fanlizhi'); alert(people.getName());//fanlizhi people.setName('小明'); alert(people.getName());//小明 alert(people.name);//undefined
通过打印出来的值你会发现他们是共用的同一个变量name。而由于是私有作用域我们只能通过实例化的对象调用特定的方法getName才能得到name的值。(function(){ var name = ""; Person = function(value){ name = value; }; Person.prototype.setName = function(value){ name = value; }; Person.prototype.getName = function(){ return name; }; })(); var people1 = new Person('fanlizhi'); alert(people1.getName());//fanlizhi people1.setName('lizhifan'); alert(people1.getName());//lizhifan var people2 = new Person('小明'); alert(people2.getName());//小明
模块模式:
前面的私有变量也属于模块模式,但是还有一种模式,那就是为单例创建的私有变量和特权方法,所谓的单例,就是说只有一个实例对象,共享相同的属性,我们前面的静态私有变量是多个实例对象共享相同的属性。先给一个简单的例子体会一下单例:
var person = {
name:'fanlizhi',
method:function(){
//具体方法
}
};
就是指大家都用的是同一个对象person。继续看看我们说的单例私有变量:
var person = function(){
var privateName = 'fanlizhi';
function callName(){
alert(privateName);
}
return {
publicShowName : function(){
callName();
}
}
}();
person.publicShowName();//fanlizhi
这个就是大家能够用一个对象共享相同的方法,同时私有变量name不包含在公众视野之下,只能通过特定方法publicShowName()访问。至于为什么要使用自执行函数var fun = function(){}(); 其实跟我们上面私有变量一样,需要通过私有作用域隐藏私有变量,而且不需要实例化。
下面我们来写一个函数注册组件的例子吧:
function baseComponent(){
}
function otherComponent(){
}
//定义两个组件
var app = function(){
var components = new Array();
components.push(new baseComponent());
return {
getComponentCount:function(){
return components.length;
},
registerComponent:function(component){
if(typeof component == 'object'){
components.push(component);
}
}
};
}();
alert(app.constructor);//function Object(){}
alert(app.getComponentCount());//1
app.registerComponent(new otherComponent());
alert(app.getComponentCount());//2
这是一个注册组件的例子,他只提供了注册和访问有多少个组件的方法。这里我们最后返回的对象都是Object,我们可能需要更加面向对象一些我们可能需要返回的是特有的对象,我们可以这样做同样是上面的例子,我们来改一下
function Component(){
}
function baseComponent(){
}
function otherComponent(){
}
//定义两个组件
var application = function(){
var components = new Array();
components.push(new baseComponent());
var app = new Component();
app.getComponentCount = function(){
return components.length;
};
app.registerComponent = function(component){
if(typeof component == 'object'){
components.push(component);
}
}
return app;
}();
alert(application.constructor);//function Component() {}
alert(application.getComponentCount());//1
application.registerComponent(new otherComponent());
alert(application.getComponentCount());//2