call和apply方法
作用:调用函数并改变函数内this的指向
语法:
两种方法都是属于函数对象的,所以必须是函数对象才能调用
functionName.call(obj,实参1,实参2...)
functionName.apply(obj,[参数1,参数2...])
区别:
- 都是改变函数内this的指向
- call方法参数是一个一个传递,而apply是传递一个参数数组
特殊情况:如果传递的第一个伪造对象是null或undefined,则函数内this会指向window全局对象
function test(a,b){
console.log(this,a,b)
}
test.call(null,10,20)
test.apply(undefined,[10,20])
什么时候用call或apply
理解:call或apply就是一种高端调用函数的方式
- 可改变函数内this指向
- 改变传参的方式
bind方法
- bind的作用和call/apply差不多,都是改变函数内this的指向。区别在于,bind不是立即执行,而是返回一个新函数。
- bind方法也是是属于
函数对象的,所以必须是函数对象才可以调用。
functionName.bind(obj,实参数1,实参数2...)
function test(a, b) {
console.log(this.age, 'a:', a, ' b:', b);
}
var obj = { age: 18 }
var fn = test.bind(obj, 50, 60) // 这里test并不会立即执行而是会返回一个函数
fn()
call/apply/bind三者区别:
- 相同点:都可以改变函数内this的指向
- 不同点:call/apply是立即执行的,而bind是返回一个新函数
手撕call、apply、bind
function test(a, b) {
console.log(this)
console.log(arguments)
}
const obj = {
name: 'zs',
age: 18,
}
call
/*
1.获取第一个参数,判断context是否为undefined或null,是的话this指向window
2.创建一个临时的方法接收调用myCall的执行函数
3.获取参数并执行对应的函数
4.删除创建的临时方法,消除副作用
5.返回结果
*/
Function.prototype.myCall = function (context, ...args) {
// 判断context是否为undefined或null,是的话this指向window
context = context || window
// 创建一个临时的函数接收调用myCall的执行函数
context.fn = this
// this为调用myCall的函数,即function test(){}
console.log(this)
// 获取参数并执行对应的函数
let res = context.fn(...args)
// 删除创建的临时方法
delete context.fn
// 返回结果
return res
}
test.myCall(obj, 1, 2)
/* 输出结果为:
ƒ test(a, b) {
console.log(this)
console.log(arguments)
}
{name: 'zs', age: 18}
Arguments(2)
*/
apply
/*
apply与call非常类似,只是传入第二个参数(args)时需要传一个数组
*/
Function.prototype.myApply = function (context, args) {
// 判断context是否为undefined或null,是的话this指向window
context = context || window
// 创建一个临时的函数接收调用myCall的执行函数
context.fn = this
// this为调用myCall的函数,即function test(){}
console.log(this)
// 获取参数并执行对应的函数
let res = context.fn(...args)
// 删除创建的临时方法
delete context.fn
// 返回结果
return res
}
test.myApply(obj, [1, 2])
/* 输出结果为:
ƒ test(a, b) {
console.log(this)
console.log(arguments)
}
{name: 'zs', age: 18}
Arguments(2)
*/
bind
/*
bind与call与apply的最大区别是返回的是一个函数而不是立即执行
bind的参数也是一个一个传入与call类似
但是bind会有两拨参数,第一组参数是调用bind(...args1),第二组参数是调用bind后返回的函数function (...args2)
*/
Function.prototype.myBind = function (context, ...args1) {
// 判断context是否为undefined或null,是的话this指向window
context = context || window
context.fn = this
// bind最大区别就是返回一个函数而不是立即执行
return function (...args2) {
context.fn(...args1, ...args2)
delete context.fn
}
}
let res = test.myBind(obj, 1, 2, 3)
res(4, 5, 6)
/*
输出结果为:
{name: 'zs', age: 18}
Arguments(6) // [1, 2, 3, 4, 5, 6]
*/