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')