1 首先this是和執(zhí)行上下文綁定的褐荷,而執(zhí)行上下文分為三種:
(1) 全局執(zhí)行上下文
在全局上下文中打印console.log(this),會發(fā)現(xiàn)最終是window骏掀,所以可以得出結(jié)論:全局執(zhí)行上下文中的this是指向window對象的妖滔。
(2) 函數(shù)執(zhí)行上下文
function foo(){
console.log(this);
}
foo();
執(zhí)行上邊這段代碼打印出來的也是window抠艾,所以默認情況下調(diào)用一個函數(shù)其執(zhí)行上下文中的this也是指向window的熟掂。
(3) eval執(zhí)行上下文
eval執(zhí)行上下文平時用到的比較少,這里就略過了骡楼。
根據(jù)上邊分析熔号,全局上下文中的this、和默認情況調(diào)用函數(shù)時鸟整,函數(shù)中的this都是指向window對象引镊,下邊我們來看我們是通過什么方式改變this指向的。
2 通過對象調(diào)用方法設(shè)置
var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
obj1.fn()//2
通過打印結(jié)果,我們發(fā)現(xiàn)此時的this指向obj1弟头,結(jié)論:使用對象來調(diào)用其內(nèi)部的一個方法吩抓,該方法的this是指向?qū)ο蟊旧淼?/em>。
var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
var fn2 = obj1.fn
fn2();//1
執(zhí)行這段代碼亮瓷,會發(fā)現(xiàn)this又指向了window琴拧。
通過上邊兩個例子對比,我們可以得出以下結(jié)論:
在全局環(huán)境中調(diào)用一個函數(shù)嘱支,函數(shù)內(nèi)部的this指向的是全局的window蚓胸。
通過一個對象來調(diào)用其內(nèi)部的一個方法,該方法執(zhí)行上下文中的this指向?qū)ο蟊旧怼?/em>
(this永遠指向調(diào)用它的那個對象除师。)
3 通過構(gòu)造函數(shù)設(shè)置
new一個函數(shù)時沛膳,背地里會將創(chuàng)建一個連接到prototype成員的新對象,同時this會被綁定到那個新對象上汛聚。
function Person(name,age){
// 這里的this都指向?qū)嵗? this.name = name
this.age = age
this.sayAge = function(){
console.log(this.age)
}
}
var dot = new Person('Dot',2)
dot.sayAge()//2
當new Person()時锹安,js引擎做了以下四件事情:
1 首先創(chuàng)建一個空對象 tempObj;
2 接著用Person.call方法,并將tempObj作為call方法參數(shù)倚舀;
3 然后執(zhí)行Person函數(shù)叹哭,此時的Person函數(shù)執(zhí)行上下文中的this指向了tempObj對象;
4 最后返回tempObj對象
可以用以下代碼理解整個調(diào)用構(gòu)造函數(shù)的過程:
var tempObj= {}
Person.call(tempObj)
return temObj
4 通過apply痕貌、call风罩、bind改變
4.1 applay
applay接收兩個參數(shù),第一個是this的值舵稠,第二個參數(shù)是一個參數(shù)數(shù)組超升。當?shù)谝粋€值為null、undefined時哺徊,this指向window室琢。
var arr = [1,2,3,89,46]
var max = Math.max.apply(null,arr)//89
4.2 call
call的第一個參數(shù)是this的值,后邊傳入的是一個參數(shù)列表落追。當?shù)谝粋€值為null盈滴、undefined時,this指向window轿钠。
var arr = [1, 2, 3, 89, 46]
var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4])//89
4.3 bind
和call很相似雹熬,第一個參數(shù)是this的指向,從第二個參數(shù)開始是接收的參數(shù)列表谣膳。區(qū)別在于bind方法返回值是函數(shù)以及bind接收的參數(shù)列表的使用。
bind返回值是函數(shù)
var obj = {
name: 'Dot'
}
function printName() {
console.log(this.name)
}
var dot = printName.bind(obj)
console.log(dot) // function () { … }
dot() // Dot
bind 方法不會立即執(zhí)行铅乡,而是返回一個改變了上下文 this 后的函數(shù)继谚。而原函數(shù) printName 中的 this 并沒有被改變,依舊指向全局對象 window阵幸。
bind參數(shù)列表的使用
function fn(a, b, c) {
console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');
fn('A', 'B', 'C'); // A B C
fn1('A', 'B', 'C'); // Dot A B
fn1('B', 'C'); // Dot B C
fn.call(null, 'Dot'); // Dot undefined undefined
call 是把第二個及以后的參數(shù)作為 fn 方法的實參傳進去花履,而 fn1 方法的實參實則是在 bind 中參數(shù)的基礎(chǔ)上再往后排芽世。
5
使用this謹記以下三點:
1 當函數(shù)作為對象方法調(diào)用時,函數(shù)中的this就是該對象诡壁;
2 當函數(shù)正常調(diào)用時济瓢,在嚴格模式下,this值是undefined妹卿,非嚴格模式下this指向的是全局的window旺矾;
3 嵌套函數(shù)中的this不會繼承外層的this值。