真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網站制作重慶分公司

詳解JS中的this、apply、call、bind(經典面試題)

這又是一個面試經典問題~/(ㄒoㄒ)/~~也是 ES5中眾多坑中的一個,在 ES6 中可能會極大避免 this 產生的錯誤,但是為了一些老代碼的維護,最好還是了解一下 this 的指向和 call、apply、bind 三者的區(qū)別。

綠春ssl適用于網站、小程序/APP、API接口等需要進行數據傳輸應用場景,ssl證書未來市場廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18982081108(備注:SSL證書合作)期待與您的合作!

this 的指向

在 ES5 中,其實 this 的指向,始終堅持一個原理:this 永遠指向最后調用它的那個對象,來,跟著我朗讀三遍:this 永遠指向最后調用它的那個對象,this 永遠指向最后調用它的那個對象,this 永遠指向最后調用它的那個對象。記住這句話,this 你已經了解一半了。

下面我們來看一個最簡單的例子:

例 1:

 var name = "windowsName";
 function a() {
  var name = "Cherry";
  console.log(this.name);   // windowsName
  console.log("inner:" + this); // inner: Window
 }
 a();
 console.log("outer:" + this)   // outer: Window

這個相信大家都知道為什么 log 的是 windowsName,因為根據剛剛的那句話“this 永遠指向最后調用它的那個對象”,我們看最后調用 a 的地方 a();,前面沒有調用的對象那么就是全局對象 window,這就相當于是 window.a();注意,這里我們沒有使用嚴格模式,如果使用嚴格模式的話,全局對象就是 undefined,那么就會報錯 Uncaught TypeError: Cannot read property 'name' of undefined。

再看下這個例子:

例 2:

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

在這個例子中,函數 fn 是對象 a 調用的,所以打印的值就是 a 中的 name 的值。是不是有一點清晰了呢~

我們做一個小小的改動:

例 3:

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

這里打印 Cherry 的原因也是因為剛剛那句話“this 永遠指向最后調用它的那個對象”,最后調用它的對象仍然是對象 a。

我們再來看一下這個例子:

例 4:

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

這里為什么會打印 undefined 呢?這是因為正如剛剛所描述的那樣,調用 fn 的是 a 對象,也就是說 fn 的內部的 this 是對象 a,而對象 a 中并沒有對 name 進行定義,所以 log 的 this.name 的值是 undefined。

這個例子還是說明了:this 永遠指向最后調用它的那個對象,因為最后調用 fn 的對象是 a,所以就算 a 中沒有 name 這個屬性,也不會繼續(xù)向上一個對象尋找 this.name,而是直接輸出 undefined。

再來看一個比較坑的例子:

例 5:

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

這里你可能會有疑問,為什么不是 Cherry,這是因為雖然將 a 對象的 fn 方法賦值給變量 f 了,但是沒有調用,再接著跟我念這一句話:“this 永遠指向最后調用它的那個對象”,由于剛剛的 f 并沒有調用,所以 fn() 最后仍然是被 window 調用的。所以 this 指向的也就是 window。

由以上五個例子我們可以看出,this 的指向并不是在創(chuàng)建的時候就可以確定的,在 es5 中,永遠是this 永遠指向最后調用它的那個對象。

再來看一個例子:

例 6:

 var name = "windowsName";
 function fn() {
  var name = 'Cherry';
  innerFunction();
  function innerFunction() {
   console.log(this.name);  // windowsName
  }
 }
 fn()

讀到現(xiàn)在了應該能夠理解這是為什么了吧(o゚▽゚)o。

怎么改變 this 的指向

改變 this 的指向我總結有以下幾種方法:

使用 ES6 的箭頭函數

在函數內部使用 _this = this

使用 apply、call、bind

new 實例化一個對象

例 7:

var name = "windowsName";
 var a = {
  name : "Cherry",
  func1: function () {
   console.log(this.name)  
  },
  func2: function () {
   setTimeout( function () {
    this.func1()
   },100);
  }
 };
 a.func2()  // this.func1 is not a function

在不使用箭頭函數的情況下,是會報錯的,因為最后調用 setTimeout 的對象是 window,但是在 window 中并沒有 func1 函數。

我們在改變 this 指向這一節(jié)將把這個例子作為 demo 進行改造。

箭頭函數

眾所周知,ES6 的箭頭函數是可以避免 ES5 中使用 this 的坑的。箭頭函數的 this 始終指向函數定義時的 this,而非執(zhí)行時。,箭頭函數需要記著這句話:“箭頭函數中沒有 this 綁定,必須通過查找作用域鏈來決定其值,如果箭頭函數被非箭頭函數包含,則 this 綁定的是最近一層非箭頭函數的 this,否則,this 為 undefined”。

例 8 :

 var name = "windowsName";
 var a = {
  name : "Cherry",
  func1: function () {
   console.log(this.name)  
  },
  func2: function () {
   setTimeout( () => {
    this.func1()
   },100);
  }
 };
 a.func2()  // Cherry

在函數內部使用 _this = this

如果不使用 ES6,那么這種方式應該是最簡單的不會出錯的方式了,我們是先將調用這個函數的對象保存在變量 _this 中,然后在函數中都使用這個 _this,這樣 _this 就不會改變了。

例 9:

 var name = "windowsName";
 var a = {
  name : "Cherry",
  func1: function () {
   console.log(this.name)  
  },
  func2: function () {
   var _this = this;
   setTimeout( function() {
    _this.func1()
   },100);
  }
 };
 a.func2()  // Cherry

這個例子中,在 func2 中,首先設置 var _this = this;,這里的 this 是調用 func2 的對象 a,為了防止在 func2 中的 setTimeout 被 window 調用而導致的在 setTimeout 中的 this 為 window。我們將 this(指向變量 a) 賦值給一個變量 _this,這樣,在 func2 中我們使用 _this 就是指向對象 a 了。

使用 apply、call、bind

使用 apply、call、bind 函數也是可以改變 this 的指向的,原理稍后再講,我們先來看一下是怎么實現(xiàn)的:

使用 apply

例 10:

 var a = {
  name : "Cherry",
  func1: function () {
   console.log(this.name)
  },
  func2: function () {
   setTimeout( function () {
    this.func1()
   }.apply(a),100);
  }
 };
 a.func2()   // Cherry

使用 call

例 11:

 var a = {
  name : "Cherry",
  func1: function () {
   console.log(this.name)
  },
  func2: function () {
   setTimeout( function () {
    this.func1()
   }.call(a),100);
  }
 };
 a.func2()   // Cherry

使用 bind

例 12:

var a = {
  name : "Cherry",
  func1: function () {
   console.log(this.name)
  },
  func2: function () {
   setTimeout( function () {
    this.func1()
   }.bind(a)(),100);
  }
 };
 a.func2()   // Cherry

apply、call、bind 區(qū)別

剛剛我們已經介紹了 apply、call、bind 都是可以改變 this 的指向的,但是這三個函數稍有不同。

在 MDN 中定義 apply 如下;

apply() 方法調用一個函數, 其具有一個指定的this值,以及作為一個數組(或類似數組的對象)提供的參數

語法:

fun.apply(thisArg, [argsArray])

thisArg:在 fun 函數運行時指定的 this 值。需要注意的是,指定的 this 值并不一定是該函數執(zhí)行時真正的 this 值,如果這個函數處于非嚴格模式下,則指定為 null 或 undefined 時會自動指向全局對象(瀏覽器中就是window對象),同時值為原始值(數字,字符串,布爾值)的 this 會指向該原始值的自動包裝對象。

argsArray:一個數組或者類數組對象,其中的數組元素將作為單獨的參數傳給 fun 函數。如果該參數的值為null 或 undefined,則表示不需要傳入任何參數。從ECMAScript 5 開始可以使用類數組對象。瀏覽器兼容性請參閱本文底部內容。

apply 和 call 的區(qū)別

其實 apply 和 call 基本類似,他們的區(qū)別只是傳入的參數不同。

call 的語法為:

fun.call(thisArg[, arg1[, arg2[, ...]]])

所以 apply 和 call 的區(qū)別是 call 方法接受的是若干個參數列表,而 apply 接收的是一個包含多個參數的數組。

例 13:

var a ={
  name : "Cherry",
  fn : function (a,b) {
   console.log( a + b)
  }
 }
 var b = a.fn;
 b.apply(a,[1,2])  // 3

例 14:

var a ={
  name : "Cherry",
  fn : function (a,b) {
   console.log( a + b)
  }
 }
 var b = a.fn;
 b.call(a,1,2)  // 3

bind 和 apply、call 區(qū)別

我們先來將剛剛的例子使用 bind 試一下

 var a ={
  name : "Cherry",
  fn : function (a,b) {
   console.log( a + b)
  }
 }
 var b = a.fn;
 b.bind(a,1,2)

我們會發(fā)現(xiàn)并沒有輸出,這是為什么呢,我們來看一下 MDN 上的文檔說明:

bind()方法創(chuàng)建一個新的函數, 當被調用時,將其this關鍵字設置為提供的值,在調用新函數時,在任何提供之前提供一個給定的參數序列。

所以我們可以看出,bind 是創(chuàng)建一個新的函數,我們必須要手動去調用:

var a ={
  name : "Cherry",
  fn : function (a,b) {
   console.log( a + b)
  }
 }
 var b = a.fn;
 b.bind(a,1,2)()   // 3

總結

以上所述是小編給大家介紹的JS中的this、apply、call、bind,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對創(chuàng)新互聯(lián)網站的支持!


網站題目:詳解JS中的this、apply、call、bind(經典面試題)
鏈接地址:http://weahome.cn/article/jpdjes.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部