前端(vue)入門到精通課程,老師線上輔導:聯絡老師
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:
【相關推薦:、】
在js中,this的意思為「這個;當前」,是一個指標型變數,它動態指向當前函數的執行環境。
在不同的場景中呼叫同一個函數,this的指向也可能會發生變化,但是它永遠指向其所在函數的真實呼叫者;如果沒有呼叫者,就指向全域性物件window。
普通函數:關於this,誰呼叫就指向誰,沒有呼叫者,就指向全域性物件window。
箭頭函數:箭頭函數的this指向於函數作用域所用的物件。
在全域性下,this始終指向全域性物件window,無論是否是嚴格模式!
congsole.log()
完整的寫法是window.console.log(),window
可以省略,window呼叫了console.log()
方法,所以此時this指向window。
直接test()呼叫函數,this指向undefined,window.test()
呼叫函數this指向window。因此,在嚴格模式下, 我們對程式碼的的呼叫必須嚴格的寫出被呼叫的函數的物件,不可以有省略或者說簡寫。
非嚴格模式下,通過test()和window.test()
呼叫函數物件,this都指向window。
物件內部方法的this指向呼叫這些方法的物件,也就是誰呼叫就指向誰。
1. 一層物件:
呼叫obj.skill()
方法,返回值為蒙犽,說明此時this指向obj。
2. 二層物件:
呼叫skill2()方法的順序為,obj.obj2.skill2()
,返回值為魯班,說明skill2()
方法中的this指向obj2。
總結:
函數的定義位置不影響其this指向,this指向只和呼叫函數的物件有關。
多層巢狀的物件,內部方法的this指向離被呼叫函數最近的物件。
箭頭函數:this指向於函數作用域所用的物件。
箭頭函數的重要特徵:箭頭函數中沒有this和arguments,是真的沒有!
箭頭函數沒有自己的this指向,它會捕獲自己定義所處的外層執行環境,並且繼承這個this值,指向當前定義時所在的物件。箭頭函數的this指向在被定義的時候就確定了,之後永遠都不會改變。即使使用call()
、apply()
、bind()
等方法改變this指向也不可以。
例子1:
例子2:
由於show函數是箭頭函數,所以自身不能繫結this,因此找它的上一級作用域。如果父級作用域還是箭頭函數,就再往上找,一層一層的直到直到this的指向。
window.show()
返回值是window,所以this此時指向window;
window.obj.show(),obj
是物件,非箭頭函數,所以找到這裡就停止了,this繫結到obj上。window呼叫obj,所以obj中的this也指向window。
建構函式中的this是指向範例。
由上圖可以看出,建構函式中的this指向建構函式下建立的範例。
this這個值在一個繼承機制中,仍然是指向它原本屬於的物件,而不是從原型鏈上找到它時,它所屬於的物件。
call(a, b, c)
方法接收三個引數,第一個是this指向,第二個,三個是傳遞給函數的實參,可以是數位,字串,陣列等型別的資料型別都可以。範例:
//定義函數function fn(n1,n2){
console.log(this);
console.log(n1,n2)}//呼叫call()方法fn.call();//=>this:window;let obj = {fn:fn};fn.call(obj);
//=>this:obj;n1,n2:undefinedfn.call(1,2);//=>this: 1;n1=2,n2=undefined;fn.call(obj,1,2);//=>this: obj;n1=1,n2=2;
//Call方法的幾個特殊屬性
//非嚴格模式下fn.call(undefined);//this=>windowfn.call(null);//this=>window
//嚴格模式下"use strict"fn.call(undefined);//this=>undefinedfn.call(null);//this=>null
登入後複製
apply(a, [b])
和call基本上一致,唯一區別在於傳參方式,apply把需要傳遞給fn()
的引數放到一個陣列(或者類陣列)中傳遞進去,雖然寫的是一個陣列,但是也相當於給fn()
一個個的傳遞。
//call()的傳參方式
fn.call(obj, 1, 2);//apply()的傳參方式fn.apply(obj, [1, 2]);
登入後複製
範例:
//apply方法的使用和call方法基本相同,唯一的區別是,apply方法傳參要求是陣列型別的,陣列內可以任意形式的資料
function fn (n1,n2){
console.log(this);
console.log(n1,n2)
console.log(arguments)}let obj = {fn:fn};
//呼叫apply()方法
fn.applay(abj,[1,2]);fn.applay(abj,1,2);
//報錯
fn.applay(abj,[11,'apply',{a:123}]);
//注意第二個引數必須是陣列,否則會報錯
登入後複製
bind(a, b, c)
:語法和call一模一樣,區別在於立即執行還是等待執行,bind不相容IE6~8
bind與call的唯一區別就是call直接改變函數test的指向,而bind是生成了一個新函數test2()
,該函數改變了指向。
//call()方法:改變fn中的this,並且把fn立即執行fn.call(obj, 1, 2); //bind()方法:改變fn中的this,fn並不執行fn.bind(obj, 1, 2);
登入後複製
範例:
//bind和call方法呼叫形式類似,但是原理完全不同
fn.call(obj,10,20);//=>fn先執行,將fn內的this指向obj,並且把引數10,20傳遞給fn
fn.bind(obj,10,20)//bind是先將fn中的this指向obj,並且將引數10,20預先傳遞給fn,但是此時的fn並沒有被執行,只有fn執行時this指向和傳遞引數才有作用
fn.bind(obj,10,20);//=>不會有任何輸出
fn.bind(obj,10,20)();//=>呼叫後才會有輸出
//=>需求:點選box這個盒子的時候,需要執行fn,並且讓fn中的this指向obj
oBox.onclick=fn; //=>點選的時候執行了fn,但此時fn中的this是oBox
oBox.onclick=fn.call(opp); //=>繫結事件的時候就已經把fn立即執行了(call本身就是立即執行函數),然後把fn執行的返回值繫結給事件
oBox.onclick=fn.bind(opp);
//=>fn.bind(opp):fn調取Function.prototype上的bind方法,執行這個/*
* function(){
* fn.call(opp);
* }
*/
oBox.onclick=function(){
//=>this:oBox
fn.call(opp);
}
登入後複製
相同點:
- call、apply和bind都是JS函數的公有的內部方法,他們都是重置函數的this,改變函數的執行環節。
不同點:
- bind是建立一個新的函數,而call和aplay是用來呼叫函數;
- call和apply作用一樣,只不過call為函數提供的引數是一個個地羅列出來,而apply為函數提供的引數是一個陣列
【相關推薦:、】
以上就是一文搞懂JavaScript中的this指向問題的詳細內容,更多請關注TW511.COM其它相關文章!