幾個月之前就想要寫一些博客,記錄本身的學習歷程,但因爲各類緣由,沒能動工,2019的第一個月即將過去,今天終於下定決心抓住一月的尾巴,勤奮一把,激勵本身在2019能有所收穫。因此這第一篇,就從面試常見的考點this指向
開始吧。面試
總的來講,咱們始終要牢記的一句話就是:this始終指向最終調用它的那個對象數組
function demo () {
var a = '這是第一個demo的a'
console.log(this)
console.log(this.a)
}
demo()
// window
// undefined
複製代碼
爲何此處this.a是undefined呢?由於咱們能夠把demo當作window.demo,window對象並無a這個屬性,因此是undefined。若是但願打印出'這是第一個demo',能夠將代碼改成以下示例:bash
function demoUpdate () {
this.a = '這是第一個demo的a'
console.log(this)
console.log(this.a)
}
demoUpdate()
// window
// 這是第一個demo的a
複製代碼
var obj = {
a: '這是第二個demo的a',
func: function () {
console.log(this)
console.log(this.a)
}
}
obj.func()
// 指向obj
// 這是第二個demo
複製代碼
function Constructor () {
var a = '這是第三個demo的a'
this.a = '這是第三個demo的b'
console.log(this)
console.log(this.a)
}
var func = new Constructor()
// 指向Constructor的實例對象
// 這是第三個demo的b
複製代碼
爲何此處的this.a指向的倒是'這是第三個demo的b',而不是a呢?這就涉及到構造函數的繼承問題了,這裏用var a 聲明的a在Constructor的實例對象,也就是func中實際上並不存在,只有this.a聲明的這個a對象才被func對象繼承,存在於func中,因此當打印this.a時,打印的就是'這是第三個demo的b'app
var obj = {
a: '這是第四個demo的外層a',
child: {
a: '這是第四個demo的內層a',
func: function () {
console.log(this)
console.log(this.a)
}
}
}
obj.child.func()
// 指向obj.child
// 這是第四個demo的內層a
複製代碼
function Constructor () {
this.a = '這是第五個demo的a'
return {}
}
var b = new Constructor
console.log(b.a) //undefined
複製代碼
由於此時b指向的是Constructor生成的實例對象,而這個對象是個空對象,沒有a屬性函數
function Constructor () {
this.a = '這是第六個demo的a'
return function () {}
}
var b = new Constructor
console.log(b.a) // undefined,此時b指向的是Constructor的新的實例對象,也就是function () {}
複製代碼
再看return的不是對象的狀況學習
function Constructor () {
this.a = '這是第七個demo的a'
return 1
}
var b = new Constuctor
console.log(b.a) // 這是第七個demo的a
複製代碼
此時b指向的是新生成的Constructor的實例對象,這個實例對象的a屬性即爲:這是第七個demo的aui
function Constructor () {
this.a = '這是第八個demo的a'
return undefined
}
var b = new Constructor
console.log(b.a) // 這是第八個demo的a,理由同上
複製代碼
function Constructor () {
this.a = '這是第九個demo的a'
return null
}
var b = new Constructor
console.log(b.a) // 這是第九個demo的a
複製代碼
首先看一個沒有改變this指向時的例子this
var obj = {
a: '這是第十個demo的a',
func1: function () {
console.log(this.a)
},
func2: function () {
setTimeout( function () {
this.func1()
}, 1000)
}
}
obj.func2() // this.func1 is not a function
複製代碼
爲何此處報錯而沒有打印‘這是第十個demo的a’呢?由於當調用obj.func2時,func2中的setTimeout函數實質上是調用window對象的setTimeout函數,this指向window,而window對象沒有func1這個屬性,因此報錯spa
箭頭函數中沒有this綁定,必須經過做用域鏈決定this的值,若是箭頭函數被非箭頭函數包含,則this指向最近的一層非箭頭函數的this,不然,this爲undefinedcode
var obj = {
a: '這是第十一個demo的a',
func1: function () {
console.log(this.a)
},
func2: function () {
setTimeout(() => {
this.func1()
}, 1000)
}
}
obj.func2() // 這是第十一個demo的a
複製代碼
var obj = {
a: '這是第十二個demo的a',
func1: function () {
console.log(this.a)
},
func2: function () {
var that = this
setTimeout(function() {
that.func1()
}, 1000)
}
}
obj.func2() // 這是第十二個demo的a
複製代碼
首先區分這三個函數的區別: call和apply改變this的指向後當即執行,而bind僅綁定this的指向,並不當即執行,返回改變this指向後的函數
call和bind的參數能夠有多個,第一個參數爲綁定的this的指向,後面的參數爲傳入函數的參數
apply只有兩個參數,第一個參數爲綁定的this的指向,第二個參數爲包含傳入函數的參數的數組
以上內容爲我本身記錄的知識點,若是後面有補充的,我會繼續添加,此博客僅作記錄知識點使用,如有幸被大佬們指點,不對的還煩請指正。