apply,call,bind详解

本文详细介绍了JavaScript中apply、call和bind的区别与使用,包括它们如何改变函数内部的this指向。通过源码实现,解释了它们的参数处理方式,并提供了一个面试题,涉及原型继承和bind的高级用法,展示了如何实现一个兼容bind功能的函数,以确保构造函数的继承和正确执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

apply,call,bind详解

三者区别

  • apply,call,bind都能改变函数内部this指向
  • apply,call会运行函数且返回函数结果,区别只是参数传递方式不一样
  • bind不会运行函数,只绑定this且传参,依然返回一个函数

一、apply源码实现

实现之前,先写一下我们的测试案例

	var obj = {
		a: 1,
		b: 2
	}
	function add(c, d){
		return this.a + this.b + c + d;
	}
	console.log(add.myApply(obj)  ) //  期望能 返回3
	写之前请注意两点:
  1. apply需要运行调用函数
  2. 需绑定this指向
Function.prototype.myApply = function(context){
	if(typeof this !== 'function'){
		console.error('error: this is not a function');
	}
	// 保存this
	context.fn = this;
	// 处理参数,注意第二个参数是数组形式
	let [args] = [...arguments].slice(1);
	
	let result =  context.fn(...args);
	delete context.fn
	return result;
}

运行截图如下:
在这里插入图片描述

可以看到函数中的this.a和this.b都拿到obj中的值了,说明没问题.

二、call

call与apply大致相同,只是参数处理稍微有点区别,感兴趣的同学可以自己去试试

三、bind

要点:

  1. 更改this指向
  2. 返回的还是一个函数
  3. 参数处理
Function.prototype.myBind = function(context){
	if(typeof this !== 'function'){
		console.error('error: this is not a function');
	}
	 let self = this;
	 let args = [...arguments].slice(1);
	 let fn = function(){
		return self.apply(context, args.concat([...arguments]))
	}
	return fn;
}

测试案例不变,结果如下:

在这里插入图片描述

面试题进阶

题目: 实现如下代码中的bind,可以让success成功打印出来

function Animal(name, color) {
        this.name = name;
        this.color = color;
    }
    Animal.prototype.say = function () {
        return `I'm a ${this.color} ${this.name}`;
    }
    const Cat = Animal.bind(null, 'cat');
    const cat = new Cat('white');
    if (cat.say() === "I'm a white cat" && cat instanceof Cat && cat instanceof Animal) {
        console.log('success')
    }

这一题主要考的是继承,有几点要素:

  1. 原型继承
  2. apply只能继承对象的内部属性,不能继承其原型(prototype)
Function.prototype.bind = function (context) {
        let self = this;
        let args = Array.prototype.slice.call(arguments, 1);
        let bound = function () {
            let boundArgs = args.concat(Array.prototype.slice.call(arguments));
            self.apply(this, boundArgs);
        }
        bound.prototype = new self()
        return bound;
    }

运行成功,没有问题。
要注意这里的bind返回的应该还是一个构造函数,且能继承绑定函数的内部属性以及原型。

你学会了吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值