javascript模式(1)--私有成员

  javascript是基于对象的一门语言,没有想java等语言那样子拥有封装的特性。但是javascript可以通过闭包来进行模拟。

1、构造函数与私有成员

  可以用构造函数形成一个闭包,实现内部成员的私有化。

  


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'


这个例子在内存中应该是这个样子的:

也就是每实例化一次,都会创建私有成员。

man2.country之所以为undefined,是因为country不是对象的属性而是私有属性。所以无法通过这种原型链的方式去访问到,所以就是该对象没有这个属性。

man2.getCountry()之所以能访问到,那就是因为闭包了。因为Person构造函数在运行完之后还有一个man2.getCountry()存在,所以不会将其作用域从内存中删除--从而形成了一个闭包。当运行man2.getCountry这条语句到return country;时,由于自己的作用域中并没有country这个属性。所以顺着作用域链往上找。在上一级的作用域中找到然后返回。

2、对象字面量与私有性

  原理和第一种一样,只是写法上不同。

  

        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'    

3、原型和私有性

  以上的两种方法,都有一个共同的问题,就是没实例化一个对象都会创建一次私有成员。那有没有一种方法,可以将一些常用的私有成员只创建一次呢。答案就是利用原型。原型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'     

内存情况如下图的第二部分。第一部分为第一种情况。可以看到,和第一种比,会减少一些内存。

第一、第二个console.log为undefined原因和第一种情况是一样的。

第三、第四个log输出的原因就稍稍有点不同。首先,man1没有getCountry这个方法,所以沿着原型链在上一级的原型中找到getCountry方法然后调用getCountry方法。然后后面的部分就和第一种一样的原理了。就是闭包了。

但是这第三种方法也是有缺点的。那就是访问时要顺着原型链向上找,如果原型链很长,那也会变慢。

 

posted @ 2015-03-10 16:53  全全的前端浆糊  阅读(941)  评论(0编辑  收藏  举报