前言
看了3.0 this的前置了解堰酿,總算能知道如何判斷this的指向了良狈,那么下面的知識(shí)也不難理解了徒像。
總結(jié)
- 作為普通函數(shù)黍特,this指向window。
- 構(gòu)造器調(diào)用锯蛀,this指向返回的這個(gè)對(duì)象灭衷。
- 當(dāng)函數(shù)作為對(duì)象的方法被調(diào)用時(shí),this就會(huì)指向該對(duì)象旁涤。
- 箭頭函數(shù) 箭頭函數(shù)的this綁定看的是this所在函數(shù)定義在哪個(gè)對(duì)象下翔曲,就綁定哪個(gè)對(duì)象。如果有嵌套的情況劈愚,則this綁定到最近的一層對(duì)象上
箭頭函數(shù)this的原理
this指向的固定化瞳遍,并不是因?yàn)榧^函數(shù)內(nèi)部有綁定this的機(jī)制,實(shí)際原因是箭頭函數(shù)根本沒(méi)有自己的this菌羽,導(dǎo)致內(nèi)部的this就是外層代碼塊的this掠械。正是因?yàn)樗鼪](méi)有this,所以也就不能用作構(gòu)造函數(shù)注祖。
怎么改變this的指向呢猾蒂?
1.使用es6的箭頭函數(shù);
2.在函數(shù)內(nèi)部使用that = this氓轰;
3.使用apply婚夫,call浸卦,bind署鸡;
4.new實(shí)例化一個(gè)對(duì)象
bind,apply,call的區(qū)別
通過(guò)apply和call改變函數(shù)的this指向,他們兩個(gè)函數(shù)的第一個(gè)參數(shù)都是一樣的表示要改變指向的那個(gè)對(duì)象限嫌,第二個(gè)參數(shù)靴庆,apply是數(shù)組,而call則是arg1,arg2...這種形式怒医。bind一個(gè)是返回一個(gè)函數(shù)炉抒,并不會(huì)立即執(zhí)行第二個(gè)是帶參數(shù)(第一個(gè)參數(shù)要指向的this,后面的的參數(shù)用來(lái)傳遞
正文
一稚叹、幾種指向
1焰薄、直接作為普通函數(shù)去調(diào)用拿诸,this指向window
在全局作用域下函數(shù)直接被調(diào)用this綁定到全局對(duì)象,如調(diào)用window.fn1(this)
塞茅,this就是全局對(duì)象
console.log(this);
function fn1(){
console.log(this);
}
fn1();
2亩码、函數(shù)嵌套含有this的內(nèi)部函數(shù),執(zhí)行父函數(shù)時(shí)野瘦,this指向window
函數(shù)嵌套產(chǎn)生的內(nèi)部函數(shù)的this不是其父函數(shù)描沟,而是如fn0()
直接調(diào)用函數(shù)里的fn()
,也是直接調(diào)用this鞭光,this指向window吏廉。
function fn0(){
function fn(){
console.log(this);
}
fn()
}
fn0()
3、this在函數(shù)setTimeout惰许、setInterval中執(zhí)行席覆,this指向window
當(dāng)執(zhí)行第一個(gè)this時(shí),它指向當(dāng)前document元素汹买;當(dāng)執(zhí)行第二個(gè)this時(shí)娜睛,函數(shù)setTimeout、setInterval中的this指向window卦睹。
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
4畦戒、作為構(gòu)造函數(shù)調(diào)用,this指向創(chuàng)建的這個(gè)對(duì)象
構(gòu)造函數(shù)结序,并不直接調(diào)用this(直接調(diào)用this則是全局變量)障斋,先new一個(gè)函數(shù)創(chuàng)建一個(gè)實(shí)例,同時(shí)設(shè)置這個(gè)實(shí)例的proto屬性指向prototype屬性徐鹤,執(zhí)行當(dāng)前函數(shù)垃环,執(zhí)行中當(dāng)前的this
第一個(gè)this此時(shí)代表剛剛創(chuàng)建的這個(gè)對(duì)象(實(shí)例),然后賦值給變量p1返敬、p2遂庄、p3,在構(gòu)造函數(shù)原型上添加的printName劲赠,執(zhí)行函數(shù)時(shí)輸出的this也代表這剛剛創(chuàng)建并調(diào)用的這個(gè)對(duì)象(實(shí)例)
function Person(name){
this.name = name;
}
Person.prototype.printName = function(){
console.log(this.name);
};
var p1 = new Person('Byron');
var p2 = new Person('Casper');
var p3 = new Person('Vincent');
p1.printName();
p2.printName();
p3.printName();
5涛目、當(dāng)函數(shù)作為對(duì)象方法被調(diào)用,this指向該對(duì)象
首先obj1.fn被調(diào)用凛澎,fn前面有一個(gè)對(duì)象引用霹肝,所以首先輸出的是對(duì)象 obj1,那么this 被自然綁定到該對(duì)象塑煎,第一個(gè)輸出便是obj1沫换,fn 中的“this”是指向全局對(duì)象,因此第二個(gè)被輸出到控制臺(tái)的是全局對(duì)象最铁。
var obj1 = {
name: 'Byron',
fn : function(){
console.log(this);
}
};
obj1.fn();
//{name: "Byron", fn: ?}和全局對(duì)象
var fn2 = obj1.fn;
fn2()
假設(shè)var fn2 = obj1.fn;此時(shí)fn2被調(diào)用讯赏,所以下一個(gè)輸出的結(jié)果也是全局變量
此時(shí)fn2和fn實(shí)質(zhì)上是對(duì)同一個(gè)函數(shù)的引用垮兑,只是調(diào)用的綁定規(guī)則不一樣。
6漱挎、DOM對(duì)象綁定事件甥角,this指向事件源DOM對(duì)象
在事件處理程序中this代表事件源DOM對(duì)象(低版本IE有bug,指向了window)识樱,但是在 setTimeout函數(shù)中如果沒(méi)有提前聲明this的話嗤无,this則指向window。如this仍代表事件源DOM對(duì)象怜庸,那么就需要將this 賦值給一個(gè)新變量
document.addEventListener('click', function(e){
console.log(this);
var _document = this;
setTimeout(function(){
console.log(this);
console.log(_document);
}, 200);
}, false);
7当犯、Function.prototype.bind
bind 作為任何函數(shù)的一個(gè)原型方法,都能找到割疾。bind嚎卫,返回一個(gè)新函數(shù),并且使函數(shù)內(nèi)部的this為傳入的第一個(gè)參數(shù)
var name = 'global'
var App {
name ='app'
sayName = function(){
console.log(this.name)
}
}
App.sayName()
//app
當(dāng)調(diào)用App.sayName()時(shí)宏榕,實(shí)際就是調(diào)用函數(shù)function拓诸,輸出this.name,那么this代表的就是App里面的name,即app
假設(shè)繼續(xù)執(zhí)行:
var name = 'global'
var App {
name ='app'
sayName = function(){
console.log(this.name)
}
}
var obj1 ={
name:'nick'
}
App.sayName() //app
App.sayName.bind(window)() //global
App.sayName.bind(obj1)() // nick
App.sayName.bind(window)()
麻昼,函數(shù).bind的作用返回一個(gè)新的函數(shù)奠支,函數(shù)中若有this,那么則作為bind的第一個(gè)對(duì)象
App.sayName.bind(參數(shù))
執(zhí)行后返回一個(gè)函數(shù)(這里相當(dāng)于生成了一個(gè)新的函數(shù))抚芦,而這里傳遞的參數(shù)倍谜,如window或者再聲明一個(gè)變量,this就是這個(gè)傳遞的參數(shù)叉抡,那么繼續(xù)執(zhí)行之后尔崔,實(shí)質(zhì)上就是執(zhí)行 sayName里面的函數(shù)體,此時(shí)this === 參數(shù)
褥民,則會(huì)輸出對(duì)應(yīng)的屬性值
待續(xù)...