先“死記硬背”以下幾條規(guī)律:
1擎场、在函數(shù)體中,非顯式或隱式的簡單調(diào)用函數(shù)時泥耀,在嚴格模式下,函數(shù)內(nèi)的this會被綁定到undefined上蛔添,非嚴格模式下痰催,綁定到全局對象 window上
2、一般使用new 調(diào)用構(gòu)造函數(shù)時迎瞧,構(gòu)造函數(shù)內(nèi)的this會指向新創(chuàng)建的對象上(返回的那個對象)
3夸溶、一般通過上下文對象調(diào)用函數(shù)時,函數(shù)體內(nèi)的this會綁定到該對象上(調(diào)用函數(shù)的那個對象)
4凶硅、在箭頭函數(shù)中缝裁,this的指向是由外層作用域來決定的
一、全局環(huán)境中的this
const foo = {
name: 'shaoyou',
say: function () {
console.log(this.name) //undefined
}
}
const f1 = foo.say
f1()
say方法借助f1隱式調(diào)用足绅,函數(shù)體內(nèi)的this指向全局
二捷绑、上線文對象調(diào)用中的this
const personal = {
name: 'a',
bro: {
name: 'b',
do: function () {
console.log(this.name) //b
}
}
}
personal.bro.do()
當代碼中有嵌套關(guān)系時,this會指向最后調(diào)用它的對象
三氢妈、通過bind粹污、apply、call改變this指向
三個函數(shù)都可以改變this指向允懂,不同的是:apply(第二個參數(shù)是數(shù)組)厕怜、call會運行函數(shù),bind返回一個新函數(shù)蕾总,但是不會運行
四粥航、構(gòu)造函數(shù)和this
function Bar () {
this.user = 'shaoyou'
return {}
}
const bar = new Bar()
console.log(bar.user) //undefined
function Foo () {
this.user = 'shaoyou'
return 1
}
const result = new Foo()
console.log(result.user) //shaoyou
如果構(gòu)造函數(shù)中返回一個值,如果這個值是一個對象生百,那么this就指向返回的這個新對象递雀;如果返回的是一個基本類型,那么this仍指向?qū)嵗龑ο?/p>
五蚀浆、箭頭函數(shù)中的this
function foo () {
return () => {
console.log(this.a)
}
}
const obj1 = {
a: '1'
}
const obj2 = {
a: '2'
}
const bar = foo.call(obj1)
console.log(bar.call(obj2)) //1
foo.call改變了foo內(nèi)部的this指向缀程,將foo中this綁定到了obj1上,所以箭頭函數(shù)中(bar)的this也綁定到了obj1上市俊;使用bar.call并不能改變this的指向
六杨凑、手動實現(xiàn)bind
Function.prototype.bind = Function.prototype.bind || function (context) {
let me = this; //此時me指向調(diào)用bind的那個函數(shù),即下面的foo
let args = Array.prototype.slice.call(arguments, 1)
return function bound () {
var innerArgs = Array.prototype.slice.call(arguments)
var finalArgs = args.concat(innerArgs)
return me.apply(context, finalArgs)
}
}
function foo (a) {
this.a = a
}
let obj1 = {}
var bar = foo.bind(obj1)
摘自:《前端開發(fā)核心知識進階》一書