面试题:实现call、apply、bind

实现bind

module.exports = function(Tcontext, ...args) {
let globalThis = typeof window === "undefined" ? global : window;
let context = typeof Tcontext === "undefined" ? globalThis : Tcontext;
let withArgs = args.length != 0; //是否传参
if (!!this.prototype && typeof context === "object" && context !== null) {
//context是有效对象
return withArgs
? () => Object.assign(context, new this(...args)) //若带参,返回的函数不需要处理接收参数
: (...args) => Object.assign(context, new this(...args)); //若不带参,返回的函数需要处理接收参数
} else {
return withArgs
? ()=>this(...args)
: (...args)=>this(...args)
}
};

实现call

在实现了bind后,只需要将call转换给bind处理就可以了

module.exports = function(context, ...args){
return this.newBind(context, ...args)()
}

实现apply

实现了call后,只需要处理下参数,转换给call处理就可以了

module.exports = function(context, args){
return args instanceof Array?this.newCall(context, ...args):this.newCall(context)
}

使用

const newBind = require("./bind")
const newCall = require("./call")
const newApply = require("./apply") Function.prototype.newBind = newBind //将bind挂载到Function原型,使得任何实例可以像使用bind一般使用newBind
Function.prototype.newCall = newCall //将call挂载到Function原型,使得任何实例可以像使用call一般使用newCall
Function.prototype.newApply = newApply //将apply挂载到Function原型,使得任何实例可以像使用apply一般使用newApply

在挂载到原型上后,就可以正常使用了

测试

1、bind的测试

require(".") //导入模块

const obj = {
q: "1"
} const Parent = function(a, b){
this.a = a;
this.b = b
} //一、使用bind的函数是构造函数,context是有效对象
//测试bind带参,执行函数不带参的情况
try {
console.log(Parent.newBind(obj,3,2)())
} catch (error) {
if(error.toString()=="Illegal context") console.log("err")
else console.log("Failed")
} //测试bind带参,执行函数带参的情况 => 执行函数的参数不生效
try {
console.log(Parent.newBind(obj,3,2)(3,4))
} catch (error) {
if(error.toString()=="Illegal context") console.log("err")
else console.log("Failed")
} //测试bind不带参的情况,执行函数不带参的情况 => 执行函数的参数应为undefined
try {
console.log(Parent.newBind(obj)())
} catch (error) {
if(error.toString()=="Illegal context") console.log("err")
else console.log("Failed")
} //测试bind带参,执行函数带参的情况 => 执行函数的带参应生效
try {
console.log(Parent.newBind(obj)(3,4))
} catch (error) {
if(error.toString()=="Illegal context") console.log("err")
else console.log("Failed")
} //二、使用bind的函数是构造函数,context是无效对象
//测试bind带参,执行函数不带参的情况
console.log(Parent.newBind(null,3,2)()) //测试bind带参,执行函数带参的情况
console.log(Parent.newBind(null,3,2)(3,4)) //测试bind不带参的情况,执行函数不带参的情况
console.log(Parent.newBind(null)()) //测试bind带参,执行函数带参的情况
console.log(Parent.newBind(null)(3,4)) //三、使用bind的函数不是构造函数
console.log(Math.pow.newBind(obj, 3, 2)())
console.log(Math.pow.newBind(null, 3, 2)())
console.log(Math.pow.newBind(1, 3, 2)())
console.log(Math.pow.newBind(null)(2,3)) console.log("测试完成")

2、call的测试

require(".") //导入模块

const obj = {
q: "1"
} const Parent = function(a, b){
this.a = a;
this.b = b
} //一、使用call的函数是构造函数,context是有效对象
//测试call带参
try {
console.log(Parent.newCall(obj,3,2))
} catch (error) {
if(error.toString()=="Illegal context") console.log("err")
else console.log("Failed")
} //测试call不带参的情况 => 执行函数的参数应为undefined
try {
console.log(Parent.newCall(obj))
} catch (error) {
if(error.toString()=="Illegal context") console.log("err")
else console.log("Failed")
} //二、使用call的函数是构造函数,context是无效对象
//测试call带参
console.log(Parent.newCall(null,3,2)) //测试call不带参的情况
console.log(Parent.newCall(null)) //三、使用call的函数不是构造函数
console.log(Math.pow.newCall(obj, 3, 2))
console.log(Math.pow.newCall(null, 3, 2))
console.log(Math.pow.newCall(1, 3, 2)) console.log("测试完成")

3、apply的测试

require(".") //导入模块

const obj = {
q: "1"
} const Parent = function(a, b){
this.a = a;
this.b = b
} //一、使用apply的函数是构造函数,context是有效对象
//测试apply带参
try {
console.log(Parent.newApply(obj,[3,2]))
} catch (error) {
if(error.toString()=="Illegal context") console.log("err")
else console.log("Failed")
} //测试apply不带参的情况 => 执行函数的参数应为undefined
try {
console.log(Parent.newApply(obj))
} catch (error) {
console.log(error);
if(error.toString()=="Illegal context") console.log("err")
else console.log("Failed")
} //二、使用apply的函数是构造函数,context是无效对象
//测试apply带参
console.log(Parent.newApply(null,[3,2])) //测试apply不带参的情况
console.log(Parent.newApply(null)) //三、使用apply的函数不是构造函数
console.log(Math.pow.newApply(obj, [3, 2]))
console.log(Math.pow.newApply(null, [3, 2]))
console.log(Math.pow.newApply(1, [3, 2]))
console.log(Math.pow.newApply(1, 3, 2)) //第二个参数不为数组,结果应异常 console.log("测试完成")

经过测试,实现call、apply、bind基本功能是ok的

github地址

源码

面试题:实现call、apply、bind的更多相关文章

  1. 前端JS面试题汇总 Part 3 (宿主对象与原生对象/函数调用方式/call与apply/bind/document.write)

    原文:https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questio ...

  2. 前端面试 js 你有多了解call,apply,bind?

    函数原型链中的 apply,call 和 bind 方法是 JavaScript 中相当重要的概念,与 this 关键字密切相关,相当一部分人对它们的理解还是比较浅显,所谓js基础扎实,绕不开这些基础 ...

  3. JavaScript内置一些方法的实现原理--new关键字,call/apply/bind方法--前戏

    new关键字,call/apply/bind方法都和this的绑定有关,在学习之前,首先要理解this. 一起来学习一下this吧 首先.this是一个对象. 对象很好理解,引用类型值,可以实现如th ...

  4. this指向与call,apply,bind

    this指向与call,apply,bind ❝ 「this」问题对于每个前端同学来说相信都不陌生,在平时开发中也经常能碰到,有时候因为「this」还踩过不少坑,并且「this」问题在面试题中出现的概 ...

  5. call,apply,bind的用法

    关于call,apply,bind这三个函数的用法,是学习javascript这门语言无法越过的知识点.下边我就来好好总结一下它们三者各自的用法,及常见的应用场景. 首先看call这个函数,可以理解成 ...

  6. JavaScript中call,apply,bind方法的总结。

    why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user:"追梦子", fn:f ...

  7. call(),apply(),bind()与回调

    1.call(),apply(),bind()方法 JavaScript 中通过call或者apply用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定 ...

  8. JS 的 call apply bind 方法

    js的call apply bind 方法都很常见,目的都是为了改变某个方法的执行环境(context) call call([thisObj[,arg1[, arg2[,   [,.argN]]]] ...

  9. javascript-this,call,apply,bind简述2

    上节我们一起研究了this这个小兄弟,得出一个结论,this指向调用this所在函数(或作用域)的那个对象或作用域.不太理解的朋友可以看看上节的内容,这次我们主要探讨一下call(),apply(), ...

  10. javascript-this,call,apply,bind简述1

    最近在系统的学习面向对象方面的知识,遇到的最大拦路虎就数this的指向,call,apply,bind函数的使用,单独抽出一天时间把这几个烦人的家伙搞定,去学习更深入的内容. 首先介绍一下this的一 ...

随机推荐

  1. 4——class和struct

    class的定义看上去很像struct定义的扩展, 事实上,类定义时的关键字class完全可以替换成struct,也就是说,结构体变量也可以有成员函数. class和struct的唯一区别在于:str ...

  2. [HNOI2015]亚瑟王(概率dp)

    题面太长了就不复制了,传送门 一道做了还是很懵逼的题目,感觉以后碰到类似的还是不会,果然HNOI题目很皮. 题解传送 补充一下吧.//感觉他的博客已经写得很好了......Orz 需要的可以两边一起看 ...

  3. MySQL提示:too many connections

    1.首先查询最大连接数 show variables like '%max_connections%'; 2.检查当前的连接情况: show processlist; 3.批量kill当前的连接: 通 ...

  4. make编写教程(一)

    1. make规则 如果工程没有被编译过,则所有的c文件都要编译和链接 如果工程的某几个c文件被修改,那么只编译被修改的文件,并链接目标程序 如果工程的头文件被修改,需要编译引用了此头文件的c文件,并 ...

  5. 回炉Spring--事务及Spring源码

    声明式事务 配置文件信息: /** * @EnableTransactionManagement 开启基于注解的事务管理功能 * 1.配置数据源 * 2.配置事务管理器来管理事务 * 3.给方法上标注 ...

  6. 《DNS稳定保障系列3--快如闪电,域名解析秒级生效》

    在刚刚过去的双十一,又是一个全民狂欢的盛宴,天猫双十一的成交量高达2684亿.无数小伙伴在淘宝.天猫里买买买,今年你又剁手了多少?言归正传,在你疯狂秒杀的时候,有没有发现,今年的购物体验一如既往的好, ...

  7. BUUCTF | CODE REVIEW 1 (反序列化,md5绕过)

    <?php /** * Created by PhpStorm. * User: jinzhao * Date: 2019/10/6 * Time: 8:04 PM */ highlight_f ...

  8. [信息学奥赛一本通oj1741]电子速度 题解

    对于$100 \%$的数据,$1≤n,m≤1e6 \ \ \ 0<=x_i,y_i<20170927 \ \ \ 1≤l_i,r_i≤n $ $Solution:$ 一开始没看懂题.后来大 ...

  9. Mac上VMWare Fusion配置多台cent os

    一.创建虚拟机(准备工作) 1.使用VMWare Fusion 创建第一台虚拟机 2.选择操作系统(本次使用的是使用cent os 6.5 64bit 系统) 3.选择磁盘大小(楼主mac上的磁盘大小 ...

  10. 高并发大流量专题---3、前端优化(减少HTTP请求次数)

    高并发大流量专题---3.前端优化(减少HTTP请求次数) 一.总结 一句话总结: 图片地图:使用<map><area></area></map>标签. ...