[JavaScript學習筆記] this

module1.init($div)              // 語法糖
module1.init.call(module1,$div) // 等價

詳解

this 永遠在函數調用時確定,只是由于語法糖的存在,我們在實際使用時會受到使用場景(瀏覽器/庫)內部this指向的不同的影響。

  1. 由于語法糖的存在,我們在平常調用函數時很少使用.call(this,argument)的形式
  2. 所以如果你自己指定this,就call

例子

let module1 = {
  elment:null,
  init: ($div)=>{
    this.element = $div
    this.bindEvents()
  },
  bindEvents:function(){
    let $div = this.element
    $div.on('click', fucntion(e){
      console.log('div is clicked')
    })
    $div.on('click', 'button', this.onClickButton)
    // 瀏覽器
    // when user click button
    // fn.call('button', {target:'button',currentTarget:'button'})
    // 所以這里只跟調用時有關
    $div.on('change', 'input', function(e){
      console.log(xxx)
    })
  },
}

總結

一般情況下,

  1. 當函數作為對象方法調用時,this指向調用該方法最靠近的對象成員,因此:
  • 當函數被賦予另一個變量時,函數內部的this的指向會改變,其原因是調用他的對象有變更
  • 可以理解為對象即執行該函數的環境,在頂級作用域下執行函數,this指向全局變量(瀏覽器中為window)
var a = {
  b: {
    m: function() {
      console.log(this.p);
    },
    p: 'Hello'
  }
};

var hello = a.b.m;
hello() // undefined

var hello = a.b
hello()  // Hello
  1. 構造函數中的this默認綁定為被創建的新對象
    原理:
  1. 創建一個空對象,作為將要返回的對象實例
  2. 將這個空對象的原型指向prototype屬性
  3. 將這個空對象的值賦給函數內部的this關鍵字
  4. 開始執行構造函數內部代碼

參考前面的方法,總結為

var a = function(){
  this.balaba = 123;
}
var b 
b = {}
Object.setPrototypeOf(b, a)
a.call(b)
  1. 當函數被當做事件處理函數時,this指向觸發事件的函數

  2. 內聯事件處理函數的this指向監聽器所在的DOM元素

  3. 當函數作為嵌套函數調用時, this指向全局對象(非嚴格模式下)或者undefined(嚴格模式)而不是其外包函數的上下文

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}
o.f1()  
// Object 
// Window
    
// 上面等價于下面
var temp = function () {
  console.log(this);
};

var o = {
  f1: function () {
    console.log(this);
    var f2 = temp();
  }
}

// 解決辦法
var o = {
  f1: function() {
    console.log(this);
    var that = this;
    var f2 = function() {
      console.log(that);
    }();
  }
}

o.f1() 
// Object
// Object

怎么看this

  1. console.log()
  2. 看瀏覽器/jQuery/DOM 源代碼
  3. 看API 文檔

bind()

bind() 會返回一個新的函數,該函數有指定的this,且不被call() / apply()

bind的使用例子

根據前面總結的第3條和第5,如果需要在一個函數中的事件監聽設置this指向外包函數的this,可以用bind綁定this的指向,否則,監聽事件觸發時this會指向觸發事件的元素。

var box = document.getElementById('box');
box.x = 'box'
function outFunc() {
  this.x = 'outFunc';//給全局對象window.x賦值(相當于賦值全局變量)
  box.addEventListener('click', func.bind(this), false); // bind(this) 的this 指向outFunc() 中的this,又等于指向window
}
function func() {
  console.log(this.x); //輸出outFunc 使用bind設置this的值
}

參考:
JS中的this簡單描述
addEventListener中事件函數的this指向
MDN - JavaScript - this

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 單例模式 適用場景:可能會在場景中使用到對象,但只有一個實例,加載時并不主動創建,需要時才創建 最常見的單例模式,...
    Obeing閱讀 2,093評論 1 10
  • 工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情,實現同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,827評論 2 17
  • 轉載請著名出處 GitHub-TYRMars 文章Github地址 JavaScript基礎知識剖析 01 01-...
    TYRMars閱讀 585評論 0 7
  • 原文鏈接 Haskell和scala都支持函數的柯里化,JavaScript函數的柯里化還與JavaScript的...
    dreamapple閱讀 2,556評論 0 24
  • 1. this之謎 在JavaScript中,this是當前執行函數的上下文。因為JavaScript有4種不同的...
    百里少龍閱讀 1,023評論 0 3