对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样
func.call(this, arg1, arg2)
func.apply(this, [arg1, arg2])
apply、call 实例
// 数组追加
var array1 = [12 , "foo" , {name:"Joe"} , -2458];
var array2 = ["Doe" , 555 , 100];
Array.prototype.push.apply(array1, array2);
// array1 值为 [12 , "foo" , {name:"Joe"} , -2458 , "Doe" , 555 , 100]
// 获取数组中的最大值和最小值
var numbers = [5, 458 , 120 , -215 ];
var maxInNumbers = Math.max.apply(Math, numbers), //458
var maxInNumbers = Math.max.call(Math,5, 458 , 120 , -215); //458
// 验证是否是数组
functionisArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]'
}
bind()
bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的 this 值。
bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
this.num = 9
var mymodule = {
num: 81,
getNum: function() {
console.log(this.num)
}
}
mymodule.getNum() // 81
var getNum = mymodule.getNum
getNum() // 9, 因为在这个例子中,"this"指向全局对象
var boundGetNum = getNum.bind(mymodule)
boundGetNum() // 81
当调用 bind 函数后,bind 函数的第一个参数就是原函数作用域中 this 指向的值
function func() {
console.log(this)
}
let newFunc = func.bind({ a: 1 })
newFunc() // 打印:{a:1}
let newFunc2 = func.bind([1, 2, 3])
newFunc2() // 打印:[1,2,3]
let newFunc3 = func.bind(1)
newFunc3() // 打印:Number:{1}
let newFunc4 = func.bind(undefined / null)
newFunc4() // 打印:window
当传入为 null 或者 undefined 时,在非严格模式下,this 指向为 window。
当传入为简单值时,内部会将简单的值包装成对应类型的对象,数字就调用 Number 方法包装;字符串就调用 String 方法包装;true/false 就调用 Boolean 方法包装。要想取到原始值,可以调用 valueOf 方法。
传递的参数的顺序问题
function func(a, b, c) {
console.log(a, b, c) // 打印传入的实参
}
let newFunc = func.bind({}, 1, 2)
newFunc(3) //1,2,3
// 可以看到,在 bind 中传递的参数要先传入到原函数中。
返回的新函数被当成构造函数
// 原函数
function func(name) {
console.log(this) // 打印:通过{name:'wy'}
this.name = name
}
func.prototype.hello = function() {
console.log(this.name)
}
let obj = { a: 1 }
// 调用bind,返回新函数
let newFunc = func.bind(obj)
// 把新函数作为构造函数,创建实例
let o = new newFunc('seven')
console.log(o.hello()) // 打印:'seven'
console.log(obj) // 打印:{a:1}
新函数被当成了构造函数,原函数 func 中的 this 不再指向传入给 bind 的第一个参数,而是指向用 new 创建的实例。在通过实例 o 找原型上的方法 hello 时,能够找到原函数 func 原型上的方法。
apply、call、bind 比较
apply 、call 、bind 三者都是用来改变函数的 this 对象的指向的;
apply 、call 、bind 三者第一个参数都是 this 要指向的对象,也就是想指定的上下文;
apply 、call 、bind 三者都可以利用后续参数传参;
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。
var obj = {
x: 81
}
var foo = {
getX: function() {
return this.x
}
}
console.log(foo.getX.bind(obj)()) //81
console.log(foo.getX.call(obj)) //81
console.log(foo.getX.apply(obj)) //81