1. 程式人生 > >JavaScript中的this、apply()、call()、bind()

JavaScript中的this、apply()、call()、bind()

this

this是函式執行時基於函式的執行環境繫結的,指向最後呼叫它的那個物件。

例1:

function a(){
    var name= "Carol";
    console.log(this.user); //undefined
    console.log(this); //Window
}
a();

最後一個呼叫a的是全域性物件Window,因此a的this指向Window,this.name會輸出undefined。

例2:

 var a = {
  name: "Carol",
  fn : function () {
   console.log(this.name);  // Carol
  }
 }
 a.fn();

這裡最後一個呼叫fn的是物件a,所以fn中的this指向a,this.name會輸出Carol。

例3:

 var a = {
  name: "Carol",
  fn : function () {
   console.log(this.name);  // Carol
  }
 }
 window.a.fn();

這裡與上面同樣,因為this指向的是最後呼叫它的那個物件,在這裡還是a。

例4:

var a = {
 name : null,
 // name: "Carol",
 fn : function () {
  console.log(this.name);  // undefined
 }
}
var f = a.fn;
f();

這裡fn的this仍然是指向window的。
因為雖然fn被賦給了變數f,但是並沒有執行,所以fn的this並不是指向a的,最後f是在window裡執行的,所以fn的this還是指向window。

例5:

function fn()  
{  
    this.name = 'Carol';  
    return function(){};
}
var a = new fn;  
console.log(a.name); //undefined

以及

function fn()  
{  
    this.name = 'Carol';  
    return 1;
}
var a = new fn;  
console.log(a.name); //Carol

如果返回值是一個物件(除null外),那麼this指向的就是那個返回的物件,如果返回值不是一個物件那麼this還是指向函式的例項。

如何改變this的指向

使用ES6的箭頭函式
箭頭函式中沒有this繫結,必須通過查詢作用域鏈來決定其值,如果箭頭函式被非箭頭函式包含,則this繫結的是最近一層非箭頭函式的 this,否則,this為undefined。

用區域性變數代替this指標
在函式內部寫上var _this=this;
用_this來代替this使用。

apply()
apply()接受兩個引數,第一個引數是要繫結給this的值,第二個引數是一個引數陣列。如果第一個引數是null、undefined的話,this指向window。

var obj = {
    message: 'My name is: '
}

function getName(firstName, lastName) {
    console.log(this.message + firstName + ' ' + lastName)
}

getName.apply(obj, ['Carol', 'Lee'])// My name is: Carol Lee

call()
call()和apply()的作用一樣,都可以改變this的指向,只不過接受引數的方式不同。

var obj = {
    message: 'My name is: '
}
function getName(firstName, lastName) {
    console.log(this.message + firstName + ' ' + lastName)
}

getName.apply(obj,'Carol','Lee')// My name is: Carol Lee

bind()
bind()和上面兩種略有不同。apply()和call()都是立即執行的,而bind()返回的是一個待執行的函式,便於需要稍後再呼叫的情況。

var obj = {
    name: 'Carol'
}

function printName() {
    console.log(this.name)
}

var c = printName.bind(obj)
console.log(c)  //function() { … }
c()   //Carol

也就是bind()();才是執行改變。