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')
相关文章
相关标签/搜索