apply的用法和搭配「call和apply的區別是什麼」

隱式綁定的 this

this 實際上是在函數被調用時綁定的,它指向什麼完全取決於函數的調用方式。

var obj = {
  a: 1,
  foo: function () {
    console.log(this.a)
  }
}

var foo2 = obj.foo
obj.foo() // 1
foo2() // undefined

如果沒有指定函數的運行對象,默認的 this 會隱式的綁定到運行環境的全局對象上。

function foo() {
  console.log(this.a)
}
a = 'global'
foo() // global

看一個常見但是有點出乎意料的的例子,如果是回調函數,即使你傳入了 obj.foo 還是會丟失 this

function foo() {
  console.log(this.a)
}
function doFoo(fn) {
  fn()
}
var obj = { a: 1, foo: foo }
a = "global"
doFoo(obj.foo) // global

如果是鏈式調用呢,則是最後哪個對象調用了這個方法,this 指向誰。

function foo() {
  console.log(this.a);
}
var obj2 = { a: 11, foo: foo }
var obj1 = { a: 1, obj2: obj2 }
obj1.obj2.foo(); // 11

其實 this 的指向都有規律可言,在隱式綁定的 this 中,this 綁定的是調用它的對像。我們回過頭解釋上面例子。

第一個例子的 foo2() 和第二個例子的 foo() 其實是在 window (global) 對象上運行的,對應的打印值就合乎情理了。第三個例子涉及 JS 執行的原理,傳入的 obj.foo 被賦值到 fn 上,所以本質上是 fn = obj.foo; window.fn(),因此 this 指向了 window

顯式綁定的 this

隱式綁定的 this 能為我們帶來很多靈活性,但是有時我們需要顯式的指定函數運行的 this

比如 apply、call、bind 這三個綁定在 Function.prototype 上的函數(關於 prototype 我們會在後面的章節提到),讓我們先看看具體 API。

fun.apply(thisArg, [argsArray])
fun.call(thisArg, arg1, arg2, ...)
fun.bind(thisArg[, arg1[, arg2[, ...]]])

它們的語法十分相近,第一個參賽指定函數的 this 環境,後面的參賽指定函數需要的參數,最大的區別是 bind 不是執行 fun 而是返回一個函數,我們看看如何來用它們顯式綁定 this。

var obj1 = { a: 1 }
var obj2 = { a: 11 }
var foo = function () {
  console.log(this.a)
}
a = 'global'
foo.apply(obj1)     // 1
foo.call(obj2)      // 11
foo.bind(global)()  // global

實際情況 bind 更適合用來固定 this 環境。

var obj1 = { a: 1 }
var obj2 = { a: 11 }
var foo = function () {
  console.log(this.a)
}.bind(obj1)
foo.apply(obj2)     // 1
foo.call(obj2)      // 1

另外我們還可以使用 new=> 尖頭函數。

new 關鍵字把 this 指向實例,這個過程發生了什麼,我們會在後面章節討論。

var foo = function (a) {
  this.a = a
}
foo.prototype.sayA = function () {
  console.log(this.a)
}
var bar = new foo(2)
foo.sayA() // 2

而尖頭函數十分特別,你可以把它理解為 bind 函數的語法糖,它的 this 同外層函數的 this。

var obj = {
  a: 1,
  foo: function () {
    console.log(this) 
    setTimeout(() => {
      console.log(this) 
    })
  }
}
obj.foo() // obj { a: 1, foo: ƒ }, obj { a: 1, foo: ƒ }

總結

this 是 JavaScript 的一大難點,多年經驗的前端程序員都可能對這方面模糊。this 在大量的函數、類庫中都有使用,理清顯式綁定和隱式綁定有助於理解或書寫這類函數。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/252771.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-14 02:19
下一篇 2024-12-14 02:19

相關推薦

發表回復

登錄後才能評論