1.this的指向問題
- A.做爲對象的方法調用
- B.做爲普通函數調用
- C.構造器調用
- D.Function.prototype.call 或 Function.prototype.apply 調用
// A.當函數做爲對象的方法被調用時,this指向該對象
var obj = {
name: 'hufei',
getUserInfo: function () {
alert(this === obj)
}
}
obj.getUserInfo() // 輸出true
// B.當函數不做爲對象的屬性被調用時,也就是咱們常說的普通函數方式,此時的 this 老是指向全局對象。在瀏覽器的 JavaScript 裏,這個全局對象是 window 對象。
window.name = 'hufei'
var obj = {
name: 'hack',
getUserInfo: function () {
return this.name
}
}
var getName = obj.getUserInfo
console.log(getName()) // hufei
console.log(obj.getUserInfo()) // hack
// C.構造器調用
// 當用 new 運算符調用函數時,該函數總 會返回一個對象,一般狀況下,構造器裏的 this 就指向返回的這個對象
var getUserInfo = function () {
this.name = 'hufei'
}
var jike = new getUserInfo()
console.log(jike.name) // hufei
// 若是構造器顯式地返回了一個 object 類型的對象,那麼這次運算結果最終會返回這個對象,而不是咱們以前期待的 this
var getUserInfo = function () {
this.name = 'hufei'
return {
name: 'test'
}
}
var jike = new getUserInfo()
console.log(jike.name) // test
// D.跟普通的函數調用相比,用 Function.prototype.call 或Function.prototype.apply 能夠動態地 改變傳入函數的 this
var info1 = {
name: 'hufei',
getUserInfo: function () {
return this.name
}
}
var info2 = {
name: 'jike'
}
info1.getUserInfo() // hufei
info1.getUserInfo().call(info2) // jike
2.call、apply和bind的區別
- call和apply的做用是改變this的指向,借用其餘對象的屬性或方法。而bind的做用是接改變這個函數的this指向而且返回一個新的函數,以後再次調用這個函數的時候this都是指向bind綁定的第一個參數。
- 傳參不同,apply傳的是集合(數組),call和bind的傳參方式同樣,都是一個一個傳遞參數。
var getInfo = function (name, age, desc) {
alert(name, age, desc)
}
getInfo.apply(null, [1, 2, 3])
getInfo.call(null, 1, 2, 3)
// 改變this的指向
var info1 = {
name: 'jike'
}
var info2 = {
name: 'hack'
}
window.name = 'window'
var getInfo = function () {
alert(this.name)
}
getInfo() // window
getInfo().call(info1) // jike
getInfo().call(info2) // hack
// 借用其餘對象的方法
(function(){
Array.prototype.push.call( arguments, 3 );
console.log ( arguments ); // 輸出[1,2,3]
})( 1, 2 );
call、apply和bind的應用
// 若是一個數組咱們已知裏面全都是數字,想要知道最大的那個數,因爲Array沒有max方法,Math對象上有
// 咱們能夠根據apply傳遞參數的特性將這個數組當成參數傳入
// 最終Math.max函數調用的時候會將apply的數組裏面的參數一個一個傳入,剛好符合Math.max的參數傳遞方式
// 這樣變相的實現了數組的max方法。min方法也同理
const arr = [1,2,3,4,5,6]
const max = Math.max.apply(null, arr)
console.log(max) // 6
// 若是你想將某個函數綁定新的`this`指向而且固定先傳入幾個變量能夠在綁定的時候就傳入,以後調用新函數傳入的參數都會排在以後
const obj = {}
function test(...args) {console.log(args)}
const newFn = test.bind(obj, '靜態參數1', '靜態參數2')
newFn('動態參數3', '動態參數4')