天天看點

this和原型對象(prototype)

文章目錄

  • ​​this​​
  • ​​原型對象(prototype)​​

this

解析器在調用函數每次都會向函數内部傳遞進一個隐含的參數,這個隐含的參數就是this,this指向的是一個對象。這個對象我們稱為函數執行的 ​

​上下文對象​

​,根據函數的調用方式的不同,this會指向不同的對象:

  • 以函數的形式調用時,this永遠都是window
  • 以方法的形式調用時,this就是調用方法的那個對象

this可以讓我們的程式更加靈活,我們可以模拟一種場景,例如:定義一個方法,在對象調用它時,可以列印出自己的名字。

<script type="text/javascript">
      
      //建立一個name變量
      var name = "全局";
      
      //建立一個fun()函數
      function fun(){
        console.log(this.name);
      }
      
      //建立兩個對象
      var obj = {
          name:"孫悟空",
          sayName:fun
      };
      
      var obj2 = {
          name:"沙和尚",
          sayName:fun
      };
      
      //我們希望調用obj.sayName()時可以輸出obj的名字
      //obj.sayName();
      
      obj.sayName();
      
    </script>      

如果這個地方不使用this.name,就相當于把這個地方寫死了,在不同的對象調用這個方法時,列印出來的名字不會動态地進行變化。

原型對象(prototype)

我們所建立的每一個函數,解析器都會向函數中添加一個屬性prototype。這個屬性對應着一個對象,這個對象就是我們所謂的原型對象。如果函數作為普通函數調用prototype沒有任何作用,當函數以構造函數的形式調用時,它所建立的對象中都會有一個隐含的屬性,指向該構造函數的原型對象,我們可以通過__proto__來通路該屬性。

原型對象就相當于一個公共的區域,所有同一個類的執行個體都可以通路到這個原型對象,我們可以将對象中共有的内容,統一設定到原型對象中。

注意:當我們通路對象的一個屬性或方法時,它會先在對象自身中尋找,如果有則直接使用,如果沒有則會去原型對象中尋找,如果找到則直接使用。

以後我們建立構造函數時,可以将這些對象共有的屬性和方法,統一添加到構造函數的原型對象中,這樣不用分别為每一個對象添加,也不會影響到全局作用域,就可以使每個對象都具有這些屬性和方法了。

對于以下代碼,我們可以用一張圖去了解它:

function MyClass(){
        
      }
      
      //向MyClass的原型中添加屬性a
      MyClass.prototype.a = 123;
      
      //向MyClass的原型中添加一個方法
      MyClass.prototype.sayHello = function(){
        alert("hello");
      };
      
      var mc = new MyClass();
      
      var mc2 = new MyClass();
      
      //console.log(MyClass.prototype);
      //console.log(mc2.__proto__ == MyClass.prototype);
      
      //向mc中添加a屬性
      mc.a = "我是mc中的a";
      
      //console.log(mc2.a);
      
      mc.sayHello();      
this和原型對象(prototype)

注意:使用in檢查對象中是否含有某個屬性時,如果對象中沒有但是原型中有,也會傳回true。

是以衍生思考如果我們就隻想知道對象本身有沒有這個屬性怎麼辦呢?

解決辦法:可以使用對象的hasOwnProperty()來檢查對象自身中是否含有該屬性,使用該方法隻有當對象自身中含有屬性時,才會傳回true。

進一步思考,我們發現建立對象的時候我們壓根沒有定義hasOwnProperty()這個方法,那為什麼我們可以使用這個方法呢?

我們的第一反應肯定是:這個方法在它的原型對象中,但經過查詢發現不是!

console.log(mc.hasOwnProperty("hasOwnProperty"));   //false
console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));  //false      

這裡我們再引入一個概念:原型對象也是對象,是以它也有原型!

當我們使用一個對象的屬性或方法時,會現在自身中尋找,自身中如果有,則直接使用,如果沒有則去原型對象中尋找,如果原型對象中有,則使用,如果沒有則去原型的原型中尋找,直到找到Object對象的原型,Object對象的原型沒有原型,如果在Object原型中依然沒有找到,則傳回undefined。

console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));  //false      

繼續閱讀