首页 > 其他分享 >【面试题】手写call、apply、bind

【面试题】手写call、apply、bind

时间:2024-03-14 19:01:52浏览次数:24  
标签:面试题 const call thisArg apply foo fn

区别

相同点:

  • 都可以改变函数的this指向
  • 第一个参数都是this要指向的对象,如果没有这个参数或参数为undefined或null,则默认指向全局window
  • 都可以利用后续参数传参

不同点:

  • call可以传入多个参数;apply需要传入一个参数对象(数组或类数组);bind可以分开传参,例如:const foo = fn.bind(this, 1, 2); foo(3, 4)
  • call、apply会立即执行,bind不会立即执行,而是返回一个修改this后的函数

实现call

Function.prototype._call = function (thisArg, ...args) {
  // this指向调用_call的函数
  const fn = this
  // 如果要绑定的对象为undefined或null,则默认指向全局对象
  thisArg = thisArg !== undefined && thisArg !== null ? Object(thisArg) : window
  // 利用this的隐式绑定规则,将函数的this绑定到指定对象上
  thisArg.fn = fn
  const res = thisArg.fn(...args)
  // 删除新增的fn方法
  delete thisArg.fn

  return res
}

测试:

function foo(a, b) {
  console.log(this.name, a, b)
}

const obj = { name: 'xiaoming' }

foo.call(obj, 20, 30) // xiaoming 20 30
foo._call(obj, 20, 30) // xiaoming 20 30

实现apply

apply和call差别不大,只是传入函数参数的形式不同

完整版:

Function.prototype._apply = function (thisArg, arrArg = []) {
    const fn = this
    thisArg = (thisArg !== undefined && thisArg != null) ? Object(thisArg) : window

    thisArg.fn = fn
    const res = thisArg.fn(...arrArg)
    delete thisArg.fn
    return res
}

简化版:

Function.prototype._apply = function (thisArg, arrArg = []) {
  const fn = this;

  return fn._call(thisArg, ...arrArg);
}

测试:

function foo(a, b) {
    console.log(this.name, a, b)
}

const obj = { name: 'xiaohong' }

foo.apply(obj, [10, 20]) // xiaohong 10 20
foo._apply(obj, [10, 20]) // xiaohong 10 20

实现bind

完整版:

Function.prototype._bind = function (thisArg, ...args) {
    const fn = this
    thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
    
    // 返回一个新函数作为绑定函数
    return function (...otherArgs) {
        thisArg.fn = fn
        const res = thisArg.fn(...args, ...otherArgs)
        delete thisArg.fn
        return res
    }
}

简化版:

Function.prototype._bind = function (thisArg, ...args) {
  const fn = this;
  
  return function (...otherArgs) {
    return fn._apply(thisArg, args.concat(otherArgs));
  };
};

测试:

function foo(a, b) {
    console.log(this.name, a, b)
}

const obj = { name: 'xiaoli' }

const res = foo.bind(obj, 30)
const res1 = foo._bind(obj, 30)

res(40) // xiaoli 30 40
res1(40) // xiaoli 30 40

标签:面试题,const,call,thisArg,apply,foo,fn
From: https://www.cnblogs.com/ccboom/p/18073703

相关文章

  • Java基础面试题(6)
    76.静态方法和实例方法有何不同?静态方法和实例方法的区别主要体现在两个方面:        在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。        静......
  • Python每日三道经典面试题(九)
    1.解释re模块的split()、sub()、subn()方法?Python的re模块提供了强大的字符串处理能力,主要用于字符串的搜索、匹配、替换和拆分等操作。其中split()、sub()和subn()是re模块中常用的几个方法,用于字符串的拆分和替换。split()方法功能:split()方法用于按照匹配的模式分割......
  • 并发支持库:多线程中的std::call_once单次调用
    std::call_once中定义template<classCallable,class...Args>voidcall_once(std::once_flag&flag,Callable&&f,Args&&...args);确保函数或者代码片段在在多线程环境下,只需要执行一次。常用的场景如Init()操作或一些系统参数的获取等。此函数在POSIX中类似p......
  • 面试题 17.12. BiNodec
    树遍历的变形/***Definitionforabinarytreenode.*structTreeNode{*intval;*structTreeNode*left;*structTreeNode*right;*};*/structTreeNode*convertBiNode(structTreeNode*root){if(!root)returnNULL;if(!roo......
  • 【Java面试题-基础知识01】Java数据类型四连问?
    一、Java中的基础数据类型有哪些?Java中的基本数据类型包括:1.byte:8位有符号整数,范围为-128到127。2.short:16位有符号整数,范围为-32768到32767。3.int:32位有符号整数,范围为-2147483648到2147483647。4.long:64位有符号整数,范围为-9223372036854775808到9223372036854775807。5.......
  • JVM篇面试题 2024
    目录Java全技术栈面试题合集地址JVM篇1.描述一下JVM加载class文件的原理机制?2.Serial与ParallelGC之间的不同之处?3.Java中WeakReference与SoftReference的区别4.怎样通过Java程序来判断JVM是32位还是64位?5.32位JVM和64位JVM的最大堆内存分别是......
  • 安卓Java面试题 91- 100
     91.请描述一下Intent和IntentFilter?Intent是组件的通讯使者,可以在组件间传递消息和数据。IntentFilter是intent的筛选器,可以对intent的action,data,catgory,uri这些属性进行筛选,确定符合的目标组件......
  • python面试题
    1、字符串最后一个单词的长度importsysstr=input()    //输入字符串strarr=str.split("")//以空格分割字符串并将结果存入数组arrn=len(arr)-1  //获取数组最后一个元素的索引print(len(arr[n])) //打印最后一个元素arr[n]的长度即为最后一个......
  • Hbase常见面试题
    major和minorcompaction区别:1.minor操作:达到TTL(记录保留时间)会被移除,删除和更新的数据仅仅只是做了标记,并没有物理移除,这种合并的触发频率很高。小合并不做数据删除,因为发生频率比较高,消耗性能小。2.major操作:是对region下的hstore下的所有storefile执行合并操作,最终的......
  • .Net 面试题总结
    WPF和WinForm区别WPF:分辨率自适应,属性binding,有事件路由、命令绑定、数据模板数据模板等特性,前后分离,可创建样式动画,页面比WinForm更炫酷WinForm:自适应差,label控件不可设置透明背景区别WPFWinForm句柄整个窗口为一个句柄窗口中每个控件都是一个句柄渲染使......