一、call、apply、bind 的共同点
- 改变函数的 this 指向
- 第一个参数都是 this 要指向的对象
二、call、apply、bind 的区别
- call、apply 都是立即执行,bind 不会立即执行,因为 bind 的返回值是一个函数
- apply 第二个参数是数组,call、bind 有多个参数时要依次传参,会一一对应
应用场景
call:实现继承
apply:与数组相关,比如:Math.max
bind:改变 this, 必须调用函数
<script>
let obj = {
str: '我是张三'
}
function fun(name, age) {
this.name = name
this.age = age
// console.log(this.str);
console.log(this);
}
// fun() // undefined; 因为 this 指向 window, 且 window 不存在属性 str
// 调用
// fun.call(obj) // 立即执行: 我是张三
// fun.apply(obj) // 立即执行: 我是张三
// fun.bind(obj) // 没有输出, 因为 bind 返回值是一个函数
// console.log(fun.bind(obj));
/*
ƒ fun() {
console.log(this.str);
}
*/
// fun.bind(obj)() // 我是张三
// 传参
fun.call(obj, 'zero', 15) // {str: '我是张三', name: 'zero', age: 15}
fun.apply(obj, ['tom', 18]) // {str: '我是张三', name: 'tom', age: 18}
fun.bind(obj, 'john', 20)() // {str: '我是张三', name: 'john', age: 20}
fun.bind(obj)('john', 20) // {str: '我是张三', name: 'john', age: 20}
</script>
三、原生实现 call、apply、bind
<script>
// call()
Function.prototype.myCall = function () {
// 判断调用对象是否为函数
if (typeof this !== 'function') {
console.error("type error");
}
// 第一个参数, 非严格模式下,null 或 undefined 会转向 window
let target = arguments[0] || window
// 获取剩余参数
let arg = Array.from(arguments).splice(1)
target.fn = this
let result = target.fn(...arg)
delete target.fn
return result
}
</script>
<script>
// apply
Function.prototype.myApply = function () {
// 判断调用对象是否为函数
if (typeof this !== 'function') {
console.error("type error");
}
// 第一个参数, 非严格模式下,null 或 undefined 会转向 window
let target = arguments[0] || window
// 获取参数
let arg = arguments[1]
target.fn = this
let result = target.fn(...arg);
delete target.fn
return target
}
</script>
<script>
// bind
Function.prototype.myBind = function () {
// 判断调用对象是否为函数
if (typeof this !== 'function') {
console.error("type error");
}
// 第一个参数, 非严格模式下,null 或 undefined 会转向 window
let target = arguments[0] || window
// 获取参数
let arg = Array.from(arguments).splice(1)
target.fn = this
return function () {
target.fn(...arg)
delete target.fn
}
}
</script>