this詳解

含義

  • 既不指向函數自己,也不指向函數的詞法做用域。
  • 運行時動態綁定,並非編寫綁定,上下文取決於函數調用的各類條件。
  • 指向取決於函數被調用的位置,也是在函數調用時候發生綁定。

解析

調用棧(能夠比擬成函數調用鏈)

  • 指到達當前執行位置所調用的全部函數
  • so調用位置(函數被調用的位置,而不是聲明位置)就是當前執行函數的前一個調用
function foo() {
    // 當前調用棧 => foo
    // 當前調用位置 => global全局做用域
    
    console.log('foo')
    bar() // bar調用位置
}

function bar() {
    // 當前調用棧 => foo -> bar
    // 當前調用位置 foo
    
    console.log('bar')
}

綁定規則

  • 默認 => 獨立函數調用app

    • this默認綁定,指向全局對象
  • 隱式 => 是否存在上下文 / 被某個對象擁有或包含函數

    • 當函數引用存在上下文,this會被隱式綁定到這個上下文對象
    • 對象屬性引用鏈只對調用位置的(上一層 / 最後一層)有效
    function foo() {
        return this.a
    }
    
    const obj = {
        a: 'hello',
        foo, // 函數引用,當前上下文是obj
    }
    
    obj.foo()
  • 顯式綁定 => call, apply, bindthis

    • 硬綁定
    function foo() {
        return this.a
    }
    
    const obj = {
        a: 'hello
    }
    
    const bar = function() {
        foo.call(obj) // 顯式的強制綁定
    }
    setTimeout(bar, 300)
    bar.call(window) // 2 => 硬綁定以後this沒法再修改
  • new綁定 => 構造函數調用,實際上並不存在「構造函數」,是對函數的「構造調用」code

    • 建立(構造)一個全新的對象
    • 這個對象會被執行[[Prototype]]鏈接
    • 這個對象會綁定到函數調用的this
    • 若是函數沒有返回對象,直接返回這個新對象

注意點


隱式綁定會丟失綁定對象,從而應用默認綁定,分別有如下兩種狀況。對象

  1. 函數別名 => 引用函數自己,so默認綁定作用域

    function foo() {
        return this.a
    }
    
    const obj = {
        a: 'hello',
        foo, // 函數引用,當前上下文是obj
    }
    
    const a = 'on no, this is global'
    const bar = obj.foo // 函數別名
    bar() // 'on no, this is global'
  2. 參數傳遞 => 隱式賦值,同上io

    function foo() {
        return this.a
    }
    
    function doFoo(fn) {
        
        fn() // fn => foo
    }
    
    const obj = {
        a: 'hello',
        foo, // 函數引用,當前上下文是obj
    }
    
    const a = 'on no, this is global'
    doFoo(obj.foo) // 'on no, this is global'

優先級

  • 顯式 > 隱式
  • new > 隱式
  • new能夠修改顯式的thisconsole

    function foo(some) {
            this.a = some
        }
        
        const obj = {}
        
        const bar =  foo.bind(obj)
        bar(2)
        console.log(obj.a) // 2
        
        const baz = new bar(3)
        console.log(obj.a) // 2
        console.log(baz.a) // 3 => new 修改了this綁定
  • new中使用硬綁定 => 函數柯理化function

    function foo(a, b) {
            this.value = a + b
        }
        
        const bar = foo.bind(null, 'hello ') //這裏 this不指定,new時會修改
        const baz = new bar('world')
        baz.value // 'hello world'
相關文章
相關標籤/搜索