javascript深入了解(私有作用域)

目标:深入了解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方法。这只是一个解释私有变量的例子,我们用得更多的会是这样的:
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都是每一个实例单独拥有的,我如果想得到一个所有实例共享的私有变量呢?如果你有java或者其他面向对象语言的基础的话,你会发现我们要的其实就是静态私有变量,没有这些基础也没关系,你了解他的用途也是一样的,我们看下面的一段代码:
(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());//小明
通过打印出来的值你会发现他们是共用的同一个变量name。而由于是私有作用域我们只能通过实例化的对象调用特定的方法getName才能得到name的值。






模块模式:
前面的私有变量也属于模块模式,但是还有一种模式,那就是为单例创建的私有变量和特权方法,所谓的单例,就是说只有一个实例对象,共享相同的属性,我们前面的静态私有变量是多个实例对象共享相同的属性。先给一个简单的例子体会一下单例:
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

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值