javascript的類的學習筆記

來源:互聯網
上載者:User

js類的基本含義

我們知道,在js中,是沒有類的概念的。類的所有執行個體對象都從同一個原型對象上繼承屬性,因此,原型對象是類的核心。

類是對象的抽象,而對象是類的具體執行個體。類是抽象的,不佔用記憶體,而對象是具體的,佔用儲存空間。———百度百科

早期的javascript需求都很簡單,基本都是寫成函數的,然後是面向過程的寫法,後來慢慢的引入物件導向開發思想,再後來就慢慢寫成 類。

在js中,寫成類的本質基本都是 建構函式+原型。下面,就討論一下js類的幾種寫法:

建構函式 法

/**
    * Person類:定義一個人,有name屬性和getName方法
   */    <script>
        function Person(name){         
          this.name = name;     
              this.getName = function(){
                              return this.name;
            }
        }        //我們在這裡執行個體化幾個對象
        var p1 = new Person("trigkit4");    
           var p2 = new Person("mike");    
              console.log(p1 instanceof Person);//true
        console.log(p2 instanceof Person);//true
    </script>
由上面控制台輸出結果可知,p1和p2的確是類Person的執行個體對象。instanceof操作符左邊是待檢測類的對象,右邊是定義類的建構函式。這裡,instanceof用來檢測對象p1是否屬於Person類。

這種方式的優點是:我們可以根據參數來構造不同的對象執行個體 ,缺點是每次構造執行個體對象時都會產生getName方法,造成了記憶體的浪費 。

我們可以用一個外部函數來代替類方法,達到了每個對象共用同一個方法。改寫後的類如下:


//外部函數<script>
    function getName() { 
          return this.name;
    }    function Person(name)
    {        this.name = name;
           this.getName = getName;//
    }</script>

原型方式


<script>
    function Person(){};
    Person.prototype.name = "trigkit4";//類的屬性都放在prototype上
    Person.prototype.getName = function(){        return " I'm " + this.name;
    }    var p1 = new Person();    var p2 = new Person();    console.log(p1.name);//trigkit4
    console.log(p2.getName());//I'm trigkit4</script>
原型方式的缺點就是不能通過參數來構造對象執行個體 (一般每個對象的屬性是不相同的) ,優點是所有對象執行個體都共用getName方法(相對於建構函式方式),沒有造成記憶體浪費 。

建構函式+原型方式

取前面兩種的優點:

a、用建構函式來定義類屬性(欄位)。
b、用原型方式來定義類的方法。

<script>
    function Person(name){        this.name = name;
    }    //原型的特性可以讓對象執行個體共用getName方法
    Person.prototype.getName = function(){        return " I'm " + this.name;
    }</script>

這樣,我們就既可以構造不同屬性的對象,也可以讓對象執行個體共用方法,不會造成記憶體的浪費。

為了讓js代碼風格更緊湊,我們讓prototype方法代碼移到function Person的大括弧內。


<script>
    function Person(name){    
       this.name = name;
        Person.prototype.getName = function(){
                    return this.name;
        }
    }    var p1 = new Person('trigkit4');  
     console.log(p1.getName());//trigkit4
     </script>

補充:

首先說說類,在一個類裡我們會有以下的幾個特徵:
1. 公有方法
2. 私人方法
3. 屬性
4. 私人變數
5. 解構函式
一、建構函式法

這是經典方法,也是教科書必教的方法。它用建構函式類比"類",在其內部用this關鍵字指代執行個體對象。

  function Cat() {

    this.name = "大毛";

  }
產生執行個體的時候,使用new關鍵字。

  var cat1 = new Cat();

  alert(cat1.name); // 大毛
類的屬性和方法,還可以定義在建構函式的prototype對象之上。

  Cat.prototype.makeSound = function(){

    alert("喵喵喵");

  }
關於這種方法的詳細介紹,請看我寫的系列文章《Javascript 物件導向編程》,這裡就不多說了。它的主要缺點是,比較複雜,用到了this和prototype,編寫和閱讀都很費力。

二、Object.create()法

為瞭解決"建構函式法"的缺點,更方便地產生對象,Javascript的國際標準ECMAScript第五版(目前通行的是第三版),提出了一個新的方法Object.create()。

用這個方法,"類"就是一個對象,不是函數。

  var Cat = {

    name: "大毛",

    makeSound: function(){ alert("喵喵喵"); }

  };
然後,直接用Object.create()產生執行個體,不需要用到new。

  var cat1 = Object.create(Cat);

  alert(cat1.name); // 大毛

  cat1.makeSound(); // 喵喵喵
目前,各大瀏覽器的最新版本(包括IE9)都部署了這個方法。如果遇到老式瀏覽器,可以用下面的代碼自行部署。

  if (!Object.create) {

    Object.create = function (o) {

       function F() {}

      F.prototype = o;

      return new F();

    };

  }
這種方法比"建構函式法"簡單,但是不能實現私人屬性和私人方法,執行個體對象之間也不能共用資料,對"類"的類比不夠全面。

三、極簡主義法

荷蘭程式員Gabor de Mooij提出了一種比Object.create()更好的新方法,他稱這種方法為"極簡主義法"(minimalist approach)。這也是我推薦的方法。

3.1 封裝

這種方法不使用this和prototype,代碼部署起來非常簡單,這大概也是它被叫做"極簡主義法"的原因。

首先,它也是用一個對象類比"類"。在這個類裡面,定義一個建構函式createNew(),用來產生執行個體。

  var Cat = {

    createNew: function(){

      // some code here

    }

  };
然後,在createNew()裡面,定義一個執行個體對象,把這個執行個體對象作為傳回值。

  var Cat = {

    createNew: function(){

      var cat = {};

      cat.name = "大毛";

      cat.makeSound = function(){ alert("喵喵喵"); };

      return cat;

    }

  };
使用的時候,調用createNew()方法,就可以得到執行個體對象。

  var cat1 = Cat.createNew();

  cat1.makeSound(); // 喵喵喵
這種方法的好處是,容易理解,結構清晰優雅,符合傳統的"物件導向編程"的構造,因此可以方便地部署下面的特性。

3.2 繼承

讓一個類繼承另一個類,實現起來很方便。只要在前者的createNew()方法中,調用後者的createNew()方法即可。

先定義一個Animal類。

  var Animal = {

    createNew: function(){

      var animal = {};

      animal.sleep = function(){ alert("睡懶覺"); };

      return animal;

    }

  };
然後,在Cat的createNew()方法中,調用Animal的createNew()方法。

  var Cat = {

    createNew: function(){

      var cat = Animal.createNew();

      cat.name = "大毛";

      cat.makeSound = function(){ alert("喵喵喵"); };

      return cat;

    }

  };
這樣得到的Cat執行個體,就會同時繼承Cat類和Animal類。

  var cat1 = Cat.createNew();

  cat1.sleep(); // 睡懶覺
3.3 私人屬性和私人方法

在createNew()方法中,只要不是定義在cat對象上的方法和屬性,都是私人的。

  var Cat = {

    createNew: function(){

      var cat = {};

      var sound = "喵喵喵";

      cat.makeSound = function(){ alert(sound); };

      return cat;

    }

  };
上例的內部變數sound,外部無法讀取,只有通過cat的公有方法makeSound()來讀取。

  var cat1 = Cat.createNew();

  alert(cat1.sound); // undefined
3.4 資料共用

有時候,我們需要所有執行個體對象,能夠讀寫同一項內部資料。這個時候,只要把這個內部資料,封裝在類對象的裡面、createNew()方法的外面即可。

  var Cat = {

    sound : "喵喵喵",

    createNew: function(){

      var cat = {};

      cat.makeSound = function(){ alert(Cat.sound); };

      cat.changeSound = function(x){ Cat.sound = x; };

      return cat;

    }

  };
然後,產生兩個執行個體對象:

  var cat1 = Cat.createNew();

  var cat2 = Cat.createNew();

  cat1.makeSound(); // 喵喵喵
這時,如果有一個執行個體對象,修改了共用的資料,另一個執行個體對象也會受到影響。

  cat2.changeSound("啦啦啦");

  cat1.makeSound(); // 啦啦啦

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.