我们知道,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的更多相关文章

  1. javascript中bind,apply,call的相同和不同之处

    javasctipt中bind,apply,call的相同点是: 1,都是用来改变this的指向; 2,都可以通过后续参数进行传参; 3,第一个参数都是指定this要指向的对象; 不同点: 1,调用方 ...

  2. javascript 的bind/apply/call性能

    javascript有两种使用频率非常高的三个内置的功能:bind/apply/call.许多技术是基于高点,这些功能实现.这三个功能被用来改变的功能运行环境.从而达到代码复用的目的. 先来所说bin ...

  3. .bind.apply() 解决 new 操作符不能用与 apply 或 call 同时使用

    背景: 小明想要用数组的形式为 Cls.func 传入多个参数,他想到了以下的写法: var a = new Cls.func.apply(null, [1, 2, 3]); 然而浏览器却报错Cls. ...

  4. bind,apply,call的区别

    在Javascript中,bind, apply, call方法都可以显式绑定上下文this,这三者有何不同呢? bind只绑定this不马上执行 var person = { firstname: ...

  5. 箭头函数表达式和声名式函数表达式的区别以及 Function.prototype的bind, apply,call方法

    箭头函数不能用做构造函数 箭头函数没有arguments参数 箭头函数没有自己的this,是从作用域链上取this,是与箭头函数定义的位置有关的,与执行时谁调用无关,所以用call,apply,bin ...

  6. 浅谈JavaScript中的apply,call和bind

    apply,call,bine 这三兄弟经常让初学者感到疑惑.前两天准备面试时特地做了个比较,其实理解起来也不会太难. apply MDN上的定义: The apply() method calls ...

  7. JavaScript: bind apply call

    var foo = function(age,sex){ console.log(this.name,age,sex); }; //call将改变函数运行的context foo.call({name ...

  8. bind,apply,call区别总结

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  9. this bind apply call

    this 是当前函数运行时所属的对象bind 是指定一个函数运行时的上下文,也就是说把这个函数的this指向绑定到相应对象上,默认的暴露在全局御中的函数this指向widow对象, 严格模式下全局的t ...

随机推荐

  1. (转载)Why you shouldn't use Entity Framework with Transactions

    Why you shouldn't use Entity Framework with Transactions EntityFramework This is a .net ORM Mapper F ...

  2. python3正则提取字符串里的中文

    # -*- coding: utf-8 -*- import re #过滤掉除了中文以外的字符 str = "hello,world!!%[545]你好234世界..." str ...

  3. Angularjs优点

    数据双向绑定,前后台的更改都可以随时生效, 提供mvc开发模式模式,剥离前端各部分代码,使代码便于维护管理. 简化了你写DOM操作

  4. 学习java应该具备哪些以及怎么学习java

    JAVA为什么有前途?过去的十多年,JAVA基本每年都是全世界使用人数第一的语言.全世界数百万的IT企业构建了庞大的JAVA生态圈,大量的软件基于JAVA开发. JAVA也被誉为“计算机界的英语”. ...

  5. vue - Babel之babel-polyfill、babel-runtime、transform-runtime

    引言 babel默认只转换新的 JavaScript 语法,比如箭头函数.扩展运算(spread). 不转换新的 API,例如Iterator.Generator.Set.Maps.Proxy.Ref ...

  6. SpringBoot安装与配置

    1.环境准备 1.1.Maven安装配置 Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件. 下载Maven可执行文件 cd /usr/local ...

  7. 论redis的内存占用

    目前大部分成程序员都将一些数据放入到了缓存(redis)中,但是你是否对这个redis内存占用了解呢?下面我们就来说一下redis的内存最优使用: 1.我们首先来介绍一下我们在存入大量数据到redis ...

  8. 运输问题中产销不平衡问题(表上作业法和LINGO方法)

    对于产销不平衡问题有两种情况: 供大于求(产大于销)→增加虚拟销地 供不应求(产小于销)→增加虚拟产地 例如以下例题: 这个题中,总产量为55,总销量为60,故而我们知道这个问题属于供不应求. 1.这 ...

  9. 基于Asp.Net Core,利用ZXing来生成二维码的一般流程

    本文主要介绍如何在.net环境下,基于Asp.Net Core,利用ZXing来生成二维码的一般操作.对二维码工作原理了解,详情见:https://blog.csdn.net/weixin_36191 ...

  10. B - Bound Found POJ - 2566(尺取 + 对区间和的绝对值

    B - Bound Found POJ - 2566 Signals of most probably extra-terrestrial origin have been received and ...