也谈如何实现bind、apply、call
我们知道,JavaScript的bind、apply、call是三个非常重要的方法。bind可以返回固定this、固定参数的函数包装;apply和call可以修改成员函数this的指向。实现bind、apply、call是前端面试的高频问题,也能让我们更好地理解和掌握JavaScript的函数的相关知识。本文将介绍如何自行实现bind、apply和call。
前情提要
本文先给出如下类定义和实例定义。
// Person类,每个人有姓名,有打印姓名的方法
function Person(_name) {
this.name = _name
this.sayMyName = function (postfix) {
console.log(this.name + postfix)
}
}
// 两个实例
let alex = new Person('Alex')
let bob = new Person('Bob')
实现bind
不妨先回顾一下bind的使用方法:
let sayBobName = alex.sayMyName.bind(bob, '?')
sayBobName() // Bob?
可见:
- bind返回一个函数副本(包装过的函数),固定this和实参。this可不指向调用者
- bind是函数原型上的一个方法
了解了这两点,就不难写出实现:
function MyBind(context, ...args) {
let that = this // this是调用者,也就是被包装的函数(alex.sayMyName)
return function () { // 返回一个包装过的函数
return that.call(context, ...args) // 其返回值是以context为this的执行结果
}
}
Function.prototype.bind = MyBind
实现call
在实现bind的过程中我们用到了call。那么如何实现一个call?不妨也回顾一下call的使用方法:
alex.sayMyName.call(bob, '!') // Bob!
可见:
- bind修改当前函数的this,可使其不指向调用者
- 参数以...rest形式传入
了解了这两点,也不难写出实现:
function MyCall(context, ...args) {
context._fn = this // this是调用者,也就是当前函数。此步给context绑上该函数
// 有个细节问题是,可能需要备份原先的context._fn,避免意外覆盖
let ret = context._fn(..args) // 模仿context自己调用_fn
delete context._fn // 移除绑的函数
return ret
}
Function.prototype.call = MyCall
实现apply
apply和call的作用相同,使用方法基本类似,唯一的不同是:
- 参数以数组形式传入
故可写出实现:
function MyApply(context, args) {
return MyCall(context, ...args)
}
Function.prototype.apply = MyApply
稳定的三角
从上面我们看出,apply和call可以实现bind,那么怎么用bind实现apply和call,从而打造这一铁三角关系呢?
bind
/ \ 两两都可互相实现的三角形!
call -- apply
简单!立即执行这个函数副本就可以了!
function AnotherMyCall(context, ...args) {
return (this.bind(context, ...args))()
}
也谈如何实现bind、apply、call的更多相关文章
- javascript中bind,apply,call的相同和不同之处
javasctipt中bind,apply,call的相同点是: 1,都是用来改变this的指向; 2,都可以通过后续参数进行传参; 3,第一个参数都是指定this要指向的对象; 不同点: 1,调用方 ...
- javascript 的bind/apply/call性能
javascript有两种使用频率非常高的三个内置的功能:bind/apply/call.许多技术是基于高点,这些功能实现.这三个功能被用来改变的功能运行环境.从而达到代码复用的目的. 先来所说bin ...
- .bind.apply() 解决 new 操作符不能用与 apply 或 call 同时使用
背景: 小明想要用数组的形式为 Cls.func 传入多个参数,他想到了以下的写法: var a = new Cls.func.apply(null, [1, 2, 3]); 然而浏览器却报错Cls. ...
- bind,apply,call的区别
在Javascript中,bind, apply, call方法都可以显式绑定上下文this,这三者有何不同呢? bind只绑定this不马上执行 var person = { firstname: ...
- 箭头函数表达式和声名式函数表达式的区别以及 Function.prototype的bind, apply,call方法
箭头函数不能用做构造函数 箭头函数没有arguments参数 箭头函数没有自己的this,是从作用域链上取this,是与箭头函数定义的位置有关的,与执行时谁调用无关,所以用call,apply,bin ...
- 浅谈JavaScript中的apply,call和bind
apply,call,bine 这三兄弟经常让初学者感到疑惑.前两天准备面试时特地做了个比较,其实理解起来也不会太难. apply MDN上的定义: The apply() method calls ...
- JavaScript: bind apply call
var foo = function(age,sex){ console.log(this.name,age,sex); }; //call将改变函数运行的context foo.call({name ...
- bind,apply,call区别总结
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- this bind apply call
this 是当前函数运行时所属的对象bind 是指定一个函数运行时的上下文,也就是说把这个函数的this指向绑定到相应对象上,默认的暴露在全局御中的函数this指向widow对象, 严格模式下全局的t ...
随机推荐
- 目标检测 | 经典算法 Cascade R-CNN: Delving into High Quality Object Detection
作者从detector的overfitting at training/quality mismatch at inference问题入手,提出了基于multi-stage的Cascade R-CNN ...
- Burpsuite被动扫描流量转发插件:Passive Scan Client
编译成品:链接: https://pan.baidu.com/s/1E0vsPGgPgB9bXCW-8Yl1gw 提取码: 49eq Passive Scan Client Burpsuite被动扫描 ...
- Nginx.pid打开失败以及失效的解决方案
在启动nginx的时候报了如下的错误: 其意思是没有该文件或者是目录,通过查看之后发现确实没有该目录 cd /var/run/nginx 于是重新创建了这个文件,使用如下命令: mkdir / ...
- ASP.NET MVC升级到ASP.NET Core MVC踩坑小结
写在前面 ASP.NET Core是微软新推出的支持跨平台.高性能.开源的开发框架,它的优势不必多说,因为已经说得太多了.当然,现在依然有着数量庞大的系统运行于.NET Framework上,由于有大 ...
- 文献名:Repeat-Preserving Decoy Database for False Discovery Rate Estimation in Peptide Identication (用于肽段鉴定中错误发生率估计的能体现重复性的诱饵数据库)
文献名:Repeat-Preserving Decoy Database for False Discovery Rate Estimation in Peptide Identication (用于 ...
- nodejs使用express中静态资源托管(express.static())时遇到的bug
如下:将test.html的页面挂载在服务器上, const express= require('express') const fs= require('fs') let app = express ...
- 二、【Docker笔记】Docker的核心概念及安装
Docker主要有三大核心的概念,分别为镜像(Image).容器(Container)及仓库(Repository). 一.核心概念 1.Docker镜像 Docker镜像其实与虚拟机镜像很类似, ...
- iOS 启动时间优化
在 WWDC 2016 上首次提到了关于 App 应用启动速度优化的话题:Session 406 Optimizing App Startup Time. 一.冷启动与热启动 热启动是,APP会恢复之 ...
- linux 访问windows 共享文件
用到的方法是 CIFS (Common Internet File System)windows自己的网络文件系统 操作系统: Linux为 debian. Windows 为 windows 8 ...
- A - Jessica's Reading Problem POJ - 3320 尺取
A - Jessica's Reading Problem POJ - 3320 Jessica's a very lovely girl wooed by lots of boys. Recentl ...