javascript是基于对象的一门语言,没有想java等语言那样子拥有封装的特性。可是javascript能够经过闭包来进行模拟。javascript
一、构造函数与私有成员java
能够用构造函数造成一个闭包,实现内部成员的私有化。闭包
function Person(){
//私有成员
var country = 'cn';
//特权方法
this.getCountry = function(){
return country;
}
}
var man1 = new Person();
var man2 = new Person();
console.log(man1.country );//undefined
console.log(man2.country );//undefined
console.log( man1.getCountry() );//'cn'
console.log( man2.getCountry() );//'cn'函数
这个例子在内存中应该是这个样子的:this
也就是每实例化一次,都会建立私有成员。spa
man2.country之因此为undefined,是由于country不是对象的属性而是私有属性。因此没法经过这种原型链的方式去访问到,因此就是该对象没有这个属性。prototype
man2.getCountry()之因此能访问到,那就是由于闭包了。由于Person构造函数在运行完以后还有一个man2.getCountry()存在,因此不会将其做用域从内存中删除--从而造成了一个闭包。当运行man2.getCountry这条语句到return country;时,因为本身的做用域中并无country这个属性。因此顺着做用域链往上找。在上一级的做用域中找到而后返回。code
二、对象字面量与私有性对象
原理和第一种同样,只是写法上不一样。blog
var obj; (function(){ //私有成员 var name = 'quan'; //公共成员部分 obj = { getName: function(){ return name; } } }()) console.log( obj.getName() );//'quan'
或者下面:
var obj = (function(){ //私有成员 var name = 'quan'; //公共成员部分 return { getName: function(){ return name; } }; }()) console.log( obj.getName() );//'quan'
三、原型和私有性
以上的两种方法,都有一个共同的问题,就是没实例化一个对象都会建立一次私有成员。那有没有一种方法,能够将一些经常使用的私有成员只建立一次呢。答案就是利用原型。原型prototype也是一个对象是函数的一个属性;是利用构造函数实例化一个对象以后,对象的一个属性__proto__。
function Person(){ // } Person.prototype = (function(){ //原型中的私有成员 var country = 'cn'; //原型中的公有成员 return { getCountry: function(){ return country; } } }()) var man1 = new Person(); var man2 = new Person(); console.log(man1.country);//undefined console.log(man2.country);//undefined console.log( man1.getCountry() );//'cn' console.log( man2.getCountry() );//'cn'
内存状况以下图的第二部分。第一部分为第一种状况。能够看到,和第一种比,会减小一些内存。
第1、第二个console.log为undefined缘由和第一种状况是同样的。
第3、第四个log输出的缘由就稍稍有点不一样。首先,man1没有getCountry这个方法,因此沿着原型链在上一级的原型中找到getCountry方法而后调用getCountry方法。而后后面的部分就和第一种同样的原理了。就是闭包了。
可是这第三种方法也是有缺点的。那就是访问时要顺着原型链向上找,若是原型链很长,那也会变慢。