前端面试之手写call,apply,bind

了解下this的指向

  • 普通函数当中的this指向window
  • 对象身上的方法指向这个对象
  • 箭头函数的this执行上层作用域下的this

手写call


Function.prototype.myCall = function(context,...arg){
	context = context!== undefined && context !== null ? Object(context) : window;
	let callFn = this;//获取call
	let symbolTemp = Symbol('临时');//临时存储
	context[symbolTemp] = callFn;
	let result = context[symbolTemp](...arg);
	delete context[symbolTemp];//用后删除
	console.log(context[symbolTemp]);//undefine
	return result;
}
const testExample = {
	x: 42,
	getX: function (a,b,c) {
	  console.log('传入的参数',a,b,c);
	  return this.x;
	},
};
const test = testExample.getX;
// console.log( test.call(testExample)); 相当于变为了testExample.test();
console.log(test.myCall(testExample,10,20,30));

手写apply

  Function.prototype.myApply = function(context,argArray){
	context = context !== undefined && context !== null ? Object(context) : window;
	argArray = argArray?.length ? argArray : [];
	let callFn = this;
	let symbolTemp = Symbol('临时存储');
	context[symbolTemp] = callFn;
	return context[symbolTemp](...argArray)
  }
  const testExample = {
	x: 42,
	getX: function (a,b,c,d) {
	  console.log('查看参数',a,b,c,d);
	  return this.x;
	},
  };
  const test = testExample.getX;
  // console.log(test.apply(testExample,[10,20,30,40])); //官方用法 相当变为了testExample.test(10,20,30,40);
  console.log(test.myApply(testExample,[10,20,30,40]));

手写bind

  • 最简单版本
    • 利用了对象身上的方法被执行的时候指向的是这个对象的原理
Function.prototype.myBind = function(context,...args){
    context = context !== undefined && context !== null ? Object(context) : window;
    const callFn = this;
    const symbolTemp = Symbol('临时对象')
    context[symbolTemp] = callFn;
    return function(...argArray){
        let result = context[symbolTemp](...argArray,...args);
        delete context[symbolTemp];//用后删除
        console.log(context[symbolTemp]);//undefine
        return  result
    }
}
const testExample = {
    x: 42,
    getX: function () {
    return this.x;
},
};
const test = testExample.getX;
// console.log(test.bind(testExample)()); //官方用法
console.log( test.myBind(testExample)  ());

chat-gpt修改意见-以apply为例

  • 首先,对于传入的 context 参数,您已经考虑了一些边界情况,例如 undefinednull,并使用 Object(context) 将其转换为对象。但是,您的实现并没有考虑传递非对象的原始值(例如字符串或数字),在这种情况下,您的代码将抛出 TypeError。您可以通过使用 Object(context) 来强制将原始值转换为其包装对象,以避免这种情况。

  • 其次,对于传入的 argArray 参数,您使用了可选链式调用 ?. 来检查它是否为 null 或 undefined,并且使用 length 属性来检查其是否为空数组。这是一个很好的实践,但是如果您的代码要在较早的 JavaScript 版本中运行,则可能会出现问题。在这种情况下,您可以使用更传统的 if 语句来进行检查,例如 if (!argArray || argArray.length === 0) { argArray = []; }

  • 最后,您的实现使用了一个唯一的 Symbol 来存储函数,并将其存储在上下文对象中,然后使用调用运算符 () 来调用该函数并传递参数数组。这是一种非常聪明和安全的方法来确保不会意外覆盖上下文对象中的现有属性。但是,如果您的代码需要在旧版本的 JavaScript 中运行,则可能需要使用字符串键来存储函数,例如 context['__myApply_temp_fn'] = callFn;

  • 下面是经过改进的代码:

    Function.prototype.myApply = function(context, argArray) {
      context = Object(context);
      argArray = (argArray && argArray.length) ? argArray : [];
      let callFn = this;
      let tempKey = '__myApply_temp_fn';
      context[tempKey] = callFn;
      let result = context[tempKey](...argArray);
      delete context[tempKey];
      return result;
    };
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未成年梦想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值