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

  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方法。而後後面的部分就和第一種同樣的原理了。就是閉包了。

可是這第三種方法也是有缺點的。那就是訪問時要順着原型鏈向上找,若是原型鏈很長,那也會變慢。

相關文章
相關標籤/搜索