This詳解

this的定義:表示當前執行代碼的環境對象

所以可將 this 的剖析分爲「全局環境」 和 「函數環境」 兩種類型的環境對象javascript

1、全局環境

console.log(this === window); // true 

var a = 10;
console.log(this.a); // 10

2、函數環境

在函數內部,this 的取值取決於函數被調用時的運行環境。java

這裏涉及到內存裏的數據結構相關的知識點,當咱們定義如下字面量對象時會發生一系列的關聯關係數據結構

var obj = { name: 'Tom' };app

javascript 引擎會先在內存中生成 { name: 'Tom' } 對象,接着再把這個對象的內存地址賦值給 obj 變量,因此 obj 變量保存的只是一個內存地址而已,若是要獲取 obj.name,javascript 引擎會先從 obj 變量中拿到內存地址,而後從該地址中獲取原始對象,再返回 name 屬性。函數

而屬性值爲函數時,該函數會被保存在內存中,而後將該內存地址賦值給該屬性,所以該地址賦值給不一樣環境執行時它的做用域是不同的,而 this 對象就是指向函數當前的執行環境對象,執行環境是會在 Event Loop(事件循環)過程當中變化的,所以 this 在函數環境下是屬於運行時的。oop

var name = 'Tom'; 

var obj = { 
    name: 'Iceberg', 
    say: function() { 
        console.log('my name is ' + this.name); 
    }, 
    sub: { 
        say: function() { 
            console.log('my name is ' + this.name); 
        } 
    } 
}; 

obj.say(); // my name is Iceberg 
obj.sub.say() // my name is undefined; 

var say = obj.say; 
say(); // my name is Tom;

上面的例子說明 obj.say() 執行環境爲 obj 對象,而 obj.sub.say() 的執行環境倒是 obj.sub 對象,而對於 obj.sub 來講並無 name 屬性,所以爲 undefined;而 var say = obj.say; 則表示將 say 方法的內存地址賦值給全局變量,所以從全局變量 name 中取值。this


運用場景

接下來從 this 在函數環境下的不一樣運用場景來剖析prototype

1.事件回調函數code

var handler = { 
    nickname: 'anonymous', 
    register: function() { 
      console.log(this.nickname); 
    } 
} 
$('#registerBtn').on('click', handler.register); // undefined

以上邏輯點擊觸發後輸出的是 undefined,由於函數被當作事件觸發的回調函數執行時,this 是指向該觸發事件對應的元素,如要 this 仍然以 handler 對象爲執行環境,則可以使用函數的 bind 方法進行執行環境對象的綁定操做。對象

$('#registerBtn').on('click', handler.register.bind(handler)); // anonymous

2.構造函數
要理解 this 在構造函數中的邏輯就要理清楚構造函數在實例化過程當中都發生了什麼。

1.  function A() { 
2.  this.name = 'Tom'; 
3.  this.age = 20; 
4.  } 
5.  var a = new A();

使用 new 命令實例化構造函數 A 的過程當中會發生如下流程:

1.建立一個空對象,做爲將要返回的對象實例
2.將該空對象的原型指向構造函數的 prototype 屬性
3.將該空對象賦值給構造函數內部的 this 關鍵字
4.執行構造函數內部代碼
5.默認返回 this 對象(如 return 的爲非對象類型,如數字 123,會被忽略進而默認 return this 對象)
6.由以上邏輯可知道 this 關鍵字在構造函數中表示的是其實例對象。

bind

1.  function A() { 
2.  this.nickname = 'Tom'; 
3.  this.say = function() { 
4.  console.log(this.nickname); 
5.  } 
6.  } 
7.  var b = { nickname: 'John' }; 
8.  var a = new A(); 
9.  var say = a.say; 
10. var say1 = a.say.bind(a); 
11. var say2 = a.say.bind(b);
12. say(); // undefined
13. say1(); // Tom
14. say2(); // John

call&apply

1.  function A() { 
2.  this.name = 'Tom'; 
3.  this.sayName = function(){ 
4.  console.log(this.name); 
5.  }; 
6.  } 

8.  function B() { 
9.  this.name = 'John'; 
10.  } 

12.  var a = new A(); 
13.  a.sayName.call(new B()); // John

總結:
1.在通常函數中使用this指全局對象window
2.做爲對象方法使用時,this指向該對象
3.做爲構造函數使用時,this指向new出的實例
4.apply或call使用時,此方法第一個參數爲改變後的調用函數的對象,函數裏this指第一個參數。
5.被當作事件觸發的回調函數執行時,this 是指向該觸發事件對應的元素

題外:手寫一個new操做

//新建一個類
function Otaku(name, age) {
    this.name = name;
    this.age = age;
    //自身的屬性
    this.habit = 'pk';
}
//給類的原型上添加屬性和方法
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function() {
    console.log('I am' + this.name);
}
//實例化一個person對象
const person = new Otaku('cty', 5000);
person.sayYourName();
console.log(person);
相關文章
相關標籤/搜索