Try   HackMD

JavaScript - this

tags: JavaScript 讀書會 this

Call() & Apply() 運用

Function 調用方式

  1. fn(arguments) ( 一般調用,屬於語法糖 )
  2. fn.call(this指向, arguments) ( 隱式調用 )
  3. fn.apply(this指向, [arguments]) ( 隱式調用 )
function test() { console.log('test') } test() === test.call() // true test() === test.apply() // true

callapply 的區別僅僅是第二個參數的差異

  1. call 可以從第 2 個參數傳到 n 個參數 fn.call(undefined, 1, 2, 3, 4...)
  2. apply 在第 2 個參數傳入陣列,後面再傳入則無效 fn.apply(undefined, [1, 2, 3, 4...])

call() 可以傳入多個參數 :

function test(a, b, c){ console.log(arguments) } test.call(undefined, 1, 2, 3) // Arguments(3) [1, 2, 3]

apply() 則是傳入一個陣列參數 :

function test(a, b, c){ console.log(arguments) } test.apply(undefined, [1, 2, 3]) // Arguments(3) [1, 2, 3]

call() 傳入陣列

function test(a, b, c){ console.log(arguments) } test.call(undefined, [1, 2, 3]) // Arguments [[1, 2, 3]]

apply() 傳入多個陣列參數沒用

function test(a, b, c){ console.log(arguments) } test.apply(undefined, [1, 2, 3], [4, 5, 6], [7, 8, 9]) // Arguments(3) [1, 2, 3]

callapply 是為了改變 this 指向而存在的

const obj1 = {
  num: 20,
  fn(n) {
    console.log(this.num + n)
  }
}

const obj2 = {
  num: 15,
  fn(n) {
    console.log(this.num - n)
  }
}

obj1.fn(10) // ?
obj1.fn.call(obj2, 10) // ?
Answer1

30,由 obj1 呼叫 fn(10),因此 this 指向 obj1


Answer2

25,因為 this 已經指向 obj2,所以 obj1fn(n) 裡面所取得的 this.num 會是 obj2num: 15

如何得知 this 指向誰 ?


// 無意義的 this
function hello() {
    console.log(this)
}

hello()
  1. 嚴格模式回傳 undefined
  2. 非嚴格模式回傳 window
  3. 非嚴格模式,node.js 回傳 global

範例 :

const obj = {
  num: 1,
  hello() {
    console.log(this)
  }
}

obj.hello() // {num: 1, hello: ƒ}
const hey = obj.hello
hey() // window

誰呼叫函式,就把誰放進 call 第一個參數 :

obj.hello.call(obj) // this 指向 obj,印出 {num: 1, hello: ƒ}
hey.call() // this 指向 window,印出 Window{...}

變異題 :

const num = 10
const obj = {
  num: 20,
  fn() {
    function test(){
      console.log(this.num)
    }
    test()
  }
}

obj.fn() // ?
Anwser

答案是 undefined

真正呼叫 this 的是 test 這個函式,改成使用 call 呼叫 : test.call(),在沒有指定 call 第一個參數時,都是預設綁定全域,也就是 window

若今天外層的 num 是使用 var 宣告,則答案會是 10,但 letconst 都有自己的區塊作用域,因此在 this 指向全域下讀取不到 num,所以為 undefined

this 面試題

1. this 是什麼 ? 什麼是 this ? this 是什麼是 this ? 什麼是 this 是什麼 ? ( 夠了

Answer

每一個 function 在被執行的時候都會有一個 reference ( 參照 ) 指向 所屬的環境 ,這就是 this。

2. Function 有哪些調用的方式 ? Function 裡面的 this 又是指向誰 ?

Answer
  1. 一般調用

    fn(),function ( fn() ) 的 this 指向全域物件,非嚴格模式下為 window,嚴格模式下為 undefined

  2. 物件中調用

    obj.fn(),function ( obj.fn() ) 裡面的 this 指向呼叫他的物件 ( obj )。

  3. 建構式中調用

    const john = new Person(),建構式 ( Person ) 的 this 指向被建構的物件 ( john )。

  4. 隱式調用

    fn.call() fn.apply() fn.bind(),使用 call、apply、bind 方式將第一個參數指定 this 指向任何物件。

3. 以下這個 this 代表什麼呢 ?

function a() {
  console.log(this)
}

Answer

不知道,this 的值與作用域和程式碼位置完全無關,只跟「你如何呼叫」有關。


Reference