- 記住须板,對(duì)于function函數(shù),this就是call的第一個(gè)參數(shù)>ぢ选!绪颖!
- 箭頭函數(shù)的this定義:箭頭函數(shù)的this是在定義函數(shù)時(shí)綁定的秽荤,而不是在執(zhí)行過(guò)程中綁定的L鹧佟!窃款!
人話:箭頭函數(shù)沒(méi)有this课兄,箭頭函數(shù)里出現(xiàn)this的話,你就把它當(dāng)做普通變量晨继,看外面有沒(méi)有定義烟阐,注意啦!所以也可以說(shuō)紊扬,如果箭頭函數(shù)里出現(xiàn)了this蜒茄,那么這個(gè)this的值就是聲明箭頭函數(shù)時(shí)定義的this的值,且后面一直會(huì)是這個(gè)值餐屎,不會(huì)改變L锤稹!腹缩!- 普通函數(shù)的this定義:基于函數(shù)的執(zhí)行環(huán)境綁定的S炝!藏鹊!
人話:誰(shuí)調(diào)用我誰(shuí)就是我的this润讥;
一、分析下面的代碼
第一個(gè)
var a = {
name: "里面的name",
sayName: function () {
console.log("this.name = " + this.name);
},
};
var name = "外面的name";
function sayName() {
var sss = a.sayName;
sss(); //this.name = ?
a.sayName(); //this.name = ?
(a.sayName)(); //this.name = ?
(b = a.sayName)(); //this.name = ?
}
sayName();
1盘寡、首先遇到調(diào)用象对,一定先變成call()的形式!Q绺А勒魔!
-
sayName()
>>sayName.call(null)
,this
為window菇曲; -
sss()
>>sss.call(null)
冠绢,this
為window; -
a.sayName()
>>a.sayName.call(a)
常潮,this
為對(duì)象a弟胀,如果是對(duì)象后面接一個(gè)函數(shù),那么call的第一個(gè)參數(shù)就是這個(gè)對(duì)象喊式; -
(a.sayName)()
>>a.sayName.call(a)
孵户,this
為對(duì)象a,注意啦2砹簟夏哭!在js中,你加不加括號(hào)都是一樣的O琢J洹何址! -
(b = a.sayName)()
>>b.call(null)
,this
為window进胯,這個(gè)就相當(dāng)于上面那個(gè)sss用爪,先給b賦值,再調(diào)用b胁镐;
第二個(gè)
var length = 10;
function fn() {
console.log(this.length);
}
var obj = {
length: 5,
method: function (fn) {
fn();
arguments[0]();
},
};
obj.method(fn, 1);
2偎血、還是需要先改寫(xiě)成call()的形式!6⑵颇玷!
-
obj.method(fn, 1)
>>obj.method.call(obj,fn, 1)
,this
是對(duì)象obj宠能,arguments
是參數(shù)組成的數(shù)組[fn, 1]
亚隙; - 再往里看method函數(shù),
fn()
>>fn.call(null)
违崇,this
為window阿弃;所以第一個(gè)打印出10; -
arguments[0]()
>>arguments.0.call(arguments)
羞延,this
為arguments
人柿,arguments
的長(zhǎng)度為2挟憔,所以打印出2;
二、定時(shí)器中的this
1狰右、 如果沒(méi)有特殊指向恃轩,setInterval和setTimeout的回調(diào)函數(shù)中this的指向都是window篙程。這是因?yàn)镴S的定時(shí)器方法是定義在window下的藏畅。
2、看下面的代碼巩步,因?yàn)閮蓚€(gè)setTimeout都是在window下調(diào)用的旁赊,所以它們回調(diào)函數(shù)里面的this都是window,第一個(gè)setTimeout里的回調(diào)函數(shù)是add函數(shù)椅野,它里面的this指向window终畅,所以改動(dòng)的就不是fn里的num,第二個(gè)setTimeout打印fn.num時(shí)竟闪,那肯定還是1啦~~~
function Fn (){
console.log(this, 'this111')
this.num = 1
this.add = function (){
console.log(this, 'this222')
this.num++
}
}
const fn = new Fn()
setTimeout(fn.add,1000)
setTimeout(function(){
console.log(this, 'this333')
console.log(fn.num, 'num')
},2000)
3离福、改一下上面第一個(gè)setTimeout里的回調(diào)函數(shù),把里面的this指向fn了
function Fn (){
console.log(this, 'this111')
this.num = 1
this.add = function (){
console.log(this, 'this222')
this.num++
}
}
const fn = new Fn()
setTimeout(fn.add.bind(fn),1000)
setTimeout(function(){
console.log(this, 'this333')
console.log(fn.num, 'num')
},2000)
4炼蛤、再看一組
- 這就需要了解箭頭函數(shù)的this指向和普通函數(shù)的this指向妖爷;
- 箭頭函數(shù)的this定義:箭頭函數(shù)的this是在定義函數(shù)時(shí)綁定的,而不是在執(zhí)行過(guò)程中綁定的>ㄅ取T獭子寓!
人話:箭頭函數(shù)沒(méi)有this暗挑,箭頭函數(shù)里出現(xiàn)this的話笋除,你就把它當(dāng)做普通變量,看外面有沒(méi)有定義炸裆,注意啦垃它!所以也可以說(shuō),如果箭頭函數(shù)里出現(xiàn)了this烹看,那么這個(gè)this的值就是聲明箭頭函數(shù)時(shí)定義的this的值国拇,且后面一直會(huì)是這個(gè)值,不會(huì)改變9呤狻=戳摺! - 普通函數(shù)的this定義:基于函數(shù)的執(zhí)行環(huán)境綁定的M了肌N袢取!
人話:誰(shuí)調(diào)用我誰(shuí)就是我的this己儒; - 所以下面第一組代碼中的setTimeout(fn.y, 1000)崎岂,雖然setTimeout的this是window,但是fn.y是箭頭函數(shù)闪湾,它的this只需要看它定義時(shí)綁定的對(duì)象冲甘,那就是Fn函數(shù);
function Fn(){
this.x = function(){
console.log(this, 'thisxxx')
}
this.y = ()=>{
console.log(this, 'thisyyy')
}
}
const fn = new Fn()
fn.x()
fn.y()
setTimeout(fn.x, 1000)
setTimeout(fn.y, 1000)
var obj = {
x: function(){
console.log(this, 'thisxxx')
},
y: ()=>{
console.log(this, 'thisyyy')
}
}
obj.x()
obj.y()
setTimeout(obj.x, 1000)
setTimeout(obj.y, 1000)
三途样、綁定this的方法
this的動(dòng)態(tài)切換江醇,固然為 JavaScript 創(chuàng)造了巨大的靈活性,但也使得編程變得困難和模糊何暇。有時(shí)陶夜,需要把this固定下來(lái),避免出現(xiàn)意想不到的情況赖晶。JavaScript 提供了call律适、apply、bind
這三個(gè)方法遏插,來(lái)切換/固定this的指向捂贿。
- Function.prototype.call()
- call方法的參數(shù),應(yīng)該是一個(gè)對(duì)象胳嘲。第一個(gè)參數(shù)是this厂僧,如果第一個(gè)參數(shù)為空、null和undefined了牛,則默認(rèn)傳入全局對(duì)象颜屠。
var n = 123;
var obj = { n: 456 };
function a() {
console.log(this.n);
}
a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456
- Function.prototype.bind()
- bind方法用于將函數(shù)體內(nèi)的this綁定到某個(gè)對(duì)象辰妙,然后返回一個(gè)綁定了這個(gè)對(duì)象的新函數(shù)。
var d = new Date();
d.getTime() // 1481869925657
var print = d.getTime;
print() // Uncaught TypeError: this is not a Date object.
上面代碼中甫窟,我們將d.getTime方法賦給變量print密浑,然后調(diào)用print就報(bào)錯(cuò)了。這是因?yàn)間etTime方法內(nèi)部的this粗井,綁定Date對(duì)象的實(shí)例尔破,賦給變量print以后,內(nèi)部的this已經(jīng)不指向Date對(duì)象的實(shí)例了浇衬。
bind方法可以解決這個(gè)問(wèn)題;
var print = d.getTime.bind(d);
print() // 1481869925657
四懒构、參考下面三篇文章
1、this的值到底是什么耘擂?https://zhuanlan.zhihu.com/p/23804247
2胆剧、如何確定this;https://zhuanlan.zhihu.com/p/25991271
3醉冤、JS里為什么要有this秩霍;https://zhuanlan.zhihu.com/p/30164164