一、什么是this
A function's
this
keyword behaves a little differently in JavaScript compared to other languages. It also has some differences between strict mode and non-strict mode.
從官方文檔我們可知
- this是一個(gè)關(guān)鍵字
- this主要用在函數(shù)中
- this 在strict mode下指向有一些不同
1.1 全局環(huán)境
無論是否在strict mode初烘,在全局執(zhí)行環(huán)境中(在任何函數(shù)體外部)this 都指向全局對象涡真。(瀏覽器中window為ECMAscript規(guī)定的Global對象)
"use strict"
//在 Node 中
console.log(this) // {}
//在瀏覽器中
console.log(this) //window
console.log(this === window) //true
this.foo = "foo"
console.log(window.foo) //foo
window.bar = "bar"
console.log(this.bar) //bar
1.1.1執(zhí)行上下文(Execution Context)
在全局作用域var關(guān)鍵字聲明變量和省略聲明的變量都會添加為全局對象的屬性
var foo = "foo"
bar = "bar"
this.foo // foo
this.bar // bar
const 、let 關(guān)鍵字聲明的變量有自己的作用域
const foo = "foo"
let bar = "bar"
this.foo // undefined
this.bar // undefined
1.2 函數(shù)(運(yùn)行內(nèi))環(huán)境
在函數(shù)內(nèi)部肾筐,this的指向取決于函數(shù)被調(diào)用的方式哆料。
1.2.1函數(shù)簡單調(diào)用
//非嚴(yán)格模式下 this 的值默認(rèn)指向全局對象。
function foo() {
return this
}
// 在Node 中
foo() // Object [global]
//在瀏覽器中
foo() //window
//嚴(yán)格模式下 this 默認(rèn)為undefined吗铐。
function foo() {
"use strict"
return this
}
// 在Node 中
foo() // undefined
//在瀏覽器中
foo() // undefined
1.2.2 函數(shù)作為對象的方法調(diào)用
(1) 當(dāng)函數(shù)作為方法被調(diào)用時(shí)东亦, this 指向調(diào)用該方法的對象
var foo = {
fn:function(){
return this
}
}
foo.fn() // foo
var foo = {}
function fn() {
return this
}
foo.fn = fn
foo.fn() // foo
(2) 鏈?zhǔn)秸{(diào)用,this指向上一個(gè)綁定對象
var bar = {
fn:function(){
return this
}
}
var foo = {
bar : bar
}
foo.bar.fn() // this ->bar
(3)當(dāng)函數(shù)調(diào)用時(shí)沒有綁定任何對象,隱式丟失
// 隱式丟失
var foo = {
fn:function(){
return this
}
}
var bar = foo.fn
bar() // window
二、this與箭頭函數(shù)
2.1 箭頭函數(shù)中唬渗,this與最近作用域的this相同
var foo = {
fn: function () {
return () => {
return this
}
},
}
var bar = foo.fn()
bar() // this -> foo
fn函數(shù)返回一個(gè)匿名箭頭函數(shù),箭頭函數(shù)中的this向上一層級找,此時(shí)箭頭函數(shù)中的this = fn中的this
2.2 對象的方法中的箭頭函數(shù)
var foo = {
bar : this,
fn :() => {
return this
}
}
foo.bar // window
foo.fn() //window
此時(shí)fn函數(shù)雖然作為foo的方法調(diào)用,但由于箭頭函數(shù)向上找作用域this的緣故,箭頭函數(shù)的this指向window
三典阵、this與匿名函數(shù)
this對象是基于函數(shù)的運(yùn)行環(huán)境綁定的
因?yàn)槟涿瘮?shù)的執(zhí)行環(huán)境有全局性,因此this對象常指向window
var foo = {
fn: function () {
return function () {
return this
}
},
}
foo.fn()() // this -> window
為什么匿名函數(shù)作用域的this沒有訪問外部作用域fn中的this呢?
因?yàn)楹瘮?shù)在調(diào)用時(shí)會自動取得兩個(gè)特殊的變量,this和arguments,匿名函數(shù)本身也會取得指向window的this,一旦搜得其活動對象即停止.
那么如何訪問fn中的this呢
3.1 通過閉包保存
var foo = {
fn: function () {
var _this = this
return function () {
return _this
}
},
}
foo.fn()() // _this -> foo
3.2 通過箭頭函數(shù)訪問外部作用域
var foo = {
fn: function () {
return () => {
return this
}
},
}
foo.fn()() // this -> foo
四、this與call()和apply()
可以通過使用函數(shù)繼承自Function.prototype的call或 apply 方法將 this值綁定到調(diào)用中的特定對象镊逝。
var foo = {}
var args = []
function bar(...args) {
return this
}
bar.call(foo,...args) // this -> foo
bar.apply(foo,args) // this -> foo
call和apply的區(qū)別為,call() 方法接受的是一個(gè)參數(shù)列表壮啊,而 apply() 方法接受的是一個(gè)包含多個(gè)參數(shù)的數(shù)組。
五撑蒜、this與bind()
ECMAScript 5 引入了 Function.prototype.bind()歹啼。調(diào)用f.bind(someObject)會創(chuàng)建一個(gè)與f具有相同函數(shù)體和作用域的函數(shù),但是在這個(gè)新函數(shù)中座菠,this將永久地被綁定到了bind的第一個(gè)參數(shù)狸眼,無論這個(gè)函數(shù)是如何被調(diào)用的。
var obj = {}
function bar (){
return this
}
var foo = bar.bind(obj)
foo() // this -> obj
obj.foo = foo
obj.foo() //this -> obj
六浴滴、this與getter和setter
當(dāng)函數(shù)在一個(gè) getter 或者 setter 中被調(diào)用拓萌。用作 getter 或 setter 的函數(shù)都會把 this 綁定到設(shè)置或獲取屬性的對象。
var foo = {}
Object.defineProperty(foo ,'bar',{
get(){
return this
}
})
foo.bar // this -> foo
七升略、this與構(gòu)造函數(shù)
當(dāng)一個(gè)函數(shù)用作構(gòu)造函數(shù)時(shí)(使用new關(guān)鍵字)司志,this被綁定到構(gòu)造的新對象甜紫。
function foo(why) {
this.why = why
}
var bar = new foo("why")
bar.why // -> why
八、this與DOM事件處理函數(shù)
絕大部分瀏覽器,當(dāng)函數(shù)被用作事件處理函數(shù)時(shí)骂远,它的this指向觸發(fā)事件的元素
var btn = document.getElementsByClassName("btn")
for (var i = 0; i < btn.length; i++) {
btn[i].addEventListener('click',()=>{
return this
})
}
// this ->btn[i]
總結(jié)
非嚴(yán)格模式下,瀏覽器中
- 函數(shù)外this指向window
- 函數(shù)內(nèi)this指向取決于調(diào)用方式
- 箭頭函數(shù)this指向向上一層作用域的this
- 匿名函數(shù)this指向window