JS中的this、apply、call、bind實例分享
this 的指向
在ES5 中,其實this 的指向,始終堅持一個原理:this 永遠指向最後調用它的那個對象,來,跟著我朗讀三遍:this 永遠指向最後調用它的那個對象,this 永遠指向最後調用它的那個對象,this 永遠指向最後調用它的那個對象。記住這句話,this 你已經了解一半了。
這又是一個面試經典問題,JS中的this、apply、call、bind是一道經典面試題,最好還是了解一下 this 的指向和 call、apply、bind 三者的區別。以下就跟著腳本之家小編一起學習this、apply、call、bind的知識吧。
下面我們來看一個最簡單的例子:
範例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 這個屬性,也不會繼續向上一個對象尋找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 的指向並不是在創建的時候就可以確定的,在 es5 中,永遠是this 永遠指向最後調用它的那個對象。
再來看一個例子:
例 6:
var name = "windowsName"; function fn() { var name = 'Cherry'; innerFunction(); function innerFunction() { console.log(this.name); // windowsName } } fn()
讀到現在了應該能夠理解這是為什麼了吧(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 指向這一節將把這個例子當作 demo 來改造。
箭頭函數
眾所周知,ES6 的箭頭函數是可以避免 ES5 中使用 this 的坑的。箭頭函數的 this 總是指向函數定義時的 this,而非執行時。 ,箭頭函數需要記著這句話:「箭頭函數中沒有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 的指向的,原理稍後再講,我們先來看一下是怎麼實現的:
使用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 區別
刚刚我们已经介绍了 apply、call、bind 都是可以改变 this 的指向的,但是这三个函数稍有不同。
在 MDN 中定义 apply 如下;
apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数
语法:
fun.apply(thisArg, [argsArray])
thisArg:在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。
apply 和 call 的区别
其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。
call 的语法为:
fun.call(thisArg[, arg1[, arg2[, ...]]])
所以 apply 和 call 的区别是 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 区别
我们先来将刚刚的例子使用 bind 试一下
var a ={ name : "Cherry", fn : function (a,b) { console.log( a + b) } } var b = a.fn; b.bind(a,1,2)
我们会发现并没有输出,这是为什么呢,我们来看一下 MDN 上的文档说明:
bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
所以我们可以看出,bind 是创建一个新的函数,我们必须要手动去调用:
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實例分享的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務
