call() 與 apply() 和 bind()

起首相識this

假如想用好這幾個要領,須要先相識this被挪用體式格局差別而致使值差別的各種狀況,然後就會認識到運用這幾個要領的緣由在那裡。(能夠指定this的值)
全局高低文中this指向全局對象,函數高低文this取決於被挪用的體式格局

例:

  • 在非嚴厲形式下,全局挪用函數this默許指向全局(window)
var a = 3

function exp(){
  var a = 4
  console.log(this.a)
}

var b = exp()
// 輸出3
  • 在嚴厲形式下,由於this為其進入高低文時的值,所認為undefined

function exp(){
 "use strict"
  return this
}

console.log(exp() === undefined)
// 輸出 true

下面剖析各個挪用場所下this的值

作為函數被直接挪用

上面已寫出了這類狀況,值得注重的是,我們每每並不須要this值為window

作為要領被挪用

作為要領被挪用時,this指向要領地點的對象上
例:

var exp =  {
  obj: function context() {
     var text = "hello"
     return this 
  }
}

console.log(exp.obj() === exp)
var a = exp.obj()
console.log(a === exp)

var b = exp.obj
console.log(b() === window) //true,,注重這裏當對象的要領被全局挪用后this是b的this,則是window

//均輸出 true

作為組織函數被挪用

我們曉得組織函數建立一個對象的歷程

  1. 建立新對象
  2. 新對象作為this指向的對象
  3. 為新對象增加要領、屬性、、並返回對象

須要注重的處所:組織函數返回一個非對象範例時,建立新對象時並不阻礙this的運用,也會返回新建立的對象。然則當組織函數顯現返回一個對象時就會將這個對象賦值給變量,this的運用則無效。

function Fn (){
  this.obj = function() {
    return this
  }
}

let a = new Fn()
console.log(a.obj() === Fn) // false
console.log(a.obj() === a) //true

let newObj = {
  name: "小明"
}

function reObj (){
  this.name = "康康"
  return newObj
}

let b = new reObj()
console.log(b.name) //小明,返回的對象是newObj

進入正題,在這麼多變化中隨時都能夠失足,所以call()、apply()、bind()就供應了一個能夠指定this的體式格局

要領的運用

  1. call()

    這個要領接收多個參數,第一個參數是指定的this值,剩下的都是挪用的函數的參數列表
    fn.call(this, arg1, arg2, ...);
    假如第一個參數須如果對象,假如傳入了数字、字符串、布爾值的話this會指向該原始值的自動包裝對象

    function f(){
          console.log(this)
          console.log(arguments)
      }
      f.call() // window
      f.call({name:'小明'}) // {name: '小明'}, []
      f.call({name:'小紅'},1) // {name: '小紅'}, [1]
      f.call({name:'康康'},1,2) // {name: '康康'}, [1,2]
  2. apply()

    apply() 與call()區分在於第二個參數接收的是一個包括多個參數的數組,關於一些要領須要傳入的參數不能使數組,能夠運用apply()挪用函數使其能夠運用數組作為參數。

    var a = [1,2,3,4,5,6,7,8,9]
    sum.apply(null,a)
    //將參數a全都傳入,它會把參數作為數組傳入。
    
    //求數組的最大元素
    Math.max.apply(null,[1,2,6]) // 6

    許多運用場景都能夠被es6里的擴大運算符替換

  3. bind()

    bind()要領建立一個新的函數, 當被挪用時,將其this關鍵字設置為供應的值.

    this.name = "大牛"
    
    let obj = {
      name: "康康",
      age: 18,
      city:"上海"
    }
    
    let newObj =  {
      name: "小明",
      sayName: function() {
        console.log(this.name)
      }
    }
    
    newObj.sayName()// 小明
    
    let a = newObj.sayName.bind(obj)
    a() //康康
    
    let b = newObj.sayName
    b() //大牛
  4. 箭頭函數
    這裏說一下箭頭函數,由於箭頭函數沒有this,所以會依據作用域鏈舉行尋覓this,這也衍生了許多用法,比如在setTimeout里經常出現的高低文(作用域)題目,假如不運用箭頭函數,在函數運行時作用域就變成了全局,運用箭頭函數會使函數里用到的this綁定在setTimeout的作用域上

    var timer = {
    fn1() {
        setTimeout(function(){
            console.log(this)
        }, 10)
    },
    fn2() {
        setTimeout(()=>{
            console.log(this)
        },20)
    },
    fn3: ()=> {
        setTimeout(()=>{
            console.log(this)
        },30)        
    }
     }
     timer.fn1() //window
     timer.fn2() // timer
     timer.fn3() //window
     
     //第一個在執行時是在全局挪用,相當於 fn1.call(undefined)
     // 第二個運用箭頭函數本身沒this,使this 指向了timer
     // 第三個本身沒this的狀況下,依據箭頭函數的劃定規矩找到了最外層全局(window)
    原文作者:戴西西
    原文地址: https://segmentfault.com/a/1190000014662375
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞