this在javascript中一直像是一個(gè)惡魔般的存在,導(dǎo)致很多的前端開發(fā)者對(duì)它都抱有一定的恐懼感,畢竟它看起來是那么的變幻無常。
克服對(duì)它的恐懼,就得需要正面面對(duì)它,了解它熟悉它。對(duì)于this的解釋我覺得在《你不知道的javascript》中解釋的已經(jīng)很清楚的,這里我就不在照搬概念了。
了解this
在函數(shù)內(nèi)部this既不是指函數(shù)本身也不指函數(shù)的詞法作用域。在函數(shù)沒有調(diào)用之前,this是不確定的,只有在調(diào)用函數(shù)的時(shí)候才會(huì)確定this的指向。在函數(shù)調(diào)用時(shí),除了傳入?yún)?shù)外,js還會(huì)默認(rèn)傳遞隱形的this和arguments參數(shù)。this指的是當(dāng)前的執(zhí)行主體。那么我們?cè)趺凑业疆?dāng)前的執(zhí)行主體呢?
在js中有這么5種情況:
先看看下面幾個(gè)例子
1, 默認(rèn)綁定
function func(){
console.log(this.a)
}
var a = 'a'
func(); // a
這種情況就是默認(rèn)綁定,為啥是默認(rèn)綁定呢?因?yàn)樵谡{(diào)用函數(shù)的時(shí)候,沒有用到任何的修飾,所以只可能是默認(rèn)綁定。那么this就指向全局變量。所以,不管在什么地方調(diào)用func,this == window。需要注意的是在嚴(yán)格模式下,this不會(huì)指向全局變量,會(huì)變成undefined。
2, 隱式綁定
var name = 'global'
function fn(){
console.log(this.name)
}
let obj = {
name: 'obj',
fn: fn
}
obj.fn(); // obj
這種隱式綁定,在函數(shù)調(diào)用的時(shí)候,會(huì)把this綁定到當(dāng)前執(zhí)行者的上下文對(duì)象。也就是說obj對(duì)象在調(diào)用函數(shù)fn的時(shí)候是擁有了function fn(){},所以this就會(huì)綁定到obj對(duì)象上。隱式綁定我們只需要記住,是誰調(diào)用函數(shù),this就指向誰。
需要注意的是,在隱式綁定中this也有可能會(huì)丟失!
var name = 'global'
function fn(){
console.log(this.name)
}
let obj = {
name: 'obj',
fn: fn
}
var newFn = obj.fn;
newFn(); // global
因?yàn)榇藭r(shí)調(diào)用newFn是不帶任何修飾的,所以已經(jīng)變成了默認(rèn)綁定,這個(gè)就相當(dāng)于
var newFn = fn
3, 在構(gòu)造函數(shù)中的this
function Obj(name){
this.name = name
}
var o = new Obj('小明');
o.name // 小明
在使用new操作函數(shù)的時(shí)候,函數(shù)返回的對(duì)象就是函數(shù)內(nèi)部的this指向。
4,顯示綁定
這個(gè)就比較明顯了,一般都是會(huì)有call,apply,bind這樣的修飾符,調(diào)用這些修飾函數(shù)的函數(shù)的第一個(gè)參數(shù)就是this的指向
function func(){
console.log(this.name)
}
var name = 'global'
var newO = {
name: 'newO'
}
func.call(newO) // newO
5,箭頭函數(shù)
箭頭函數(shù)是沒有this的,那么箭頭函數(shù)內(nèi)部的this會(huì)是誰呢?它的指向是包裹該函數(shù)的外面作用域,也就是說外層是否有函數(shù)包裹,那么this就是外層函數(shù)的this;外層沒有函數(shù),那么this就是window。
var name = 'global'
function func(){
var name = 'func'
var inner = () => {
console.log(this.name)
}
return inner
}
func()() // global
function func2(){
var name = 'func2'
var inner = () => {
console.log(this.name)
}
inner()
}
func2(); // global
function func3(name) {
this.name = name;
var inner = () => {
console.log(this.name)
}
inner()
}
var obj = new func3('func3'); // func3
前兩種情況都是global,是因?yàn)楹瘮?shù)都是默認(rèn)綁定,this就是window。最后的一種情況打印func3,包含inner函數(shù)的外層函數(shù)func3的this在用new操作之后指向的是obj,所以inner箭頭函數(shù)的this,就是obj。
function func3(name) {
this.name = name;
function inner() {
console.log(this.name)
}
inner()
}
var obj = new func3('func3'); // global
如果不是箭頭函數(shù)的話,就會(huì)打印全局global。
說了一大堆,可能有同學(xué)已經(jīng)頭暈?zāi)垦A?,那么最后我們用一張圖總結(jié)一下。

如果上面說的那么多可以幫助到你,可以幫我點(diǎn)個(gè)小小的愛心支持鼓勵(lì)下。如果有講的不清楚或者不對(duì)的地方也望大佬在評(píng)論區(qū)多多指點(diǎn)共同進(jìn)步,康桑密達(dá)!