JavaScript系列之this

前言

在JavaScript語言中存在一個this關鍵詞,這個關鍵詞指的是函數運行時所在的環境。因爲函數能夠在不一樣的運行環境執行,因此須要有一種機制,可以在函數體內部得到當前的運行環境(context)。因此,this就出現了,它的設計目的就是在函數體內部,指代函數當前的運行環境。bash

前一個系列的做用域講過,做用域運用的是詞法做用域,意味着是編寫時肯定的,但this與其工做原理徹底不一樣,它的指向並非編寫時肯定的,而是運行時肯定。markdown

僅僅是「規則」

以前在閱讀 You Don't Know JS系列的: this & Object Prototypes中,將this的指向總結了幾條規則:數據結構

函數調用方式與內部this指針關係:app

  1. 直接調用:函數內部this指向全局對象window
  2. 經過對象使用點來調用:函數內部this指向調用對象
  3. 觸發事件調用函數:函數內部的this指向觸發事件的對象
  4. 經過call的方法來間接調用方法:函數內部this指向call方法的第一參數對象,咱們能夠建立結構相同,但內容不一樣的對象
  5. new的方式來調用:函數內部this指向本次函數執行時對應的一個匿名對象(以new的方式建立的函數,函數名的首字母通常以大寫字母開始)
  6. 箭頭函數的this,指向取決於函數外的上下文。箭頭函數沒法被new關鍵詞調用,經過applycall方法不會改變內部的this指向

不單單是「規則」

參考了上面的規則發現,this的指向不管如何都逃脫不了上面的5大原則,那它們以前是否存在必定的規律呢,或者說是什麼來決定this的指向的。函數

一般咱們會對一下例子的結果無法準確的肯定this指向:oop

var name = 'zhou';
var obj = {
    name: 'shaw',
    say: function () {
        console.log(this.name);
    }
}
obj.say();  

var say = obj.say;
say();
複製代碼

上面的輸出結果會是什麼呢:this

obj.say(); // 輸出shaw
say();  // 輸出zhou
複製代碼

爲何這裏obj.saysay的輸出結果會不一致呢?下面咱們來一探究竟。spa

this的指向與數據在內存裏的數據結構有關:設計

上面案例裏的obj對象是如何在內存中存儲的呢指針

obj.say-> {
    [[value]]: say函數地址
    [[write]]: true,
    [[readable]]: true
}
複製代碼

實際上say函數並無存儲在obj對象中,它只存儲了say函數的地址。

咱們直接經過obj.say來調用函數,與obj.say賦值給say變量調用徹底不一樣,由於obj中存儲的是say函數的地址,咱們進行賦值操做時直接將say函數地址直接賦值過去了,而不是咱們想象的將obj.say引用賦值過去。

相關文章
相關標籤/搜索