this、call、apply、bind

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')
相關文章
相關標籤/搜索