前端百题斩【015】——快速手撕call、apply、bind
前端 快速 call bind apply 015
2023-09-27 14:25:56 时间
在百题斩【014】中已经简要概述了call、apply、bind三个方法 这三者作用是相同的 均可以改变this指向 从而让某对象可以调用自身不具备的方法 本节将深入理解这三者的实现原理。
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。其返回值是使用调用者提供的this值和参数调用该函数的返回值 若该方法没有返回值 则返回undefined。
基本用法
function.call(thisArg, arg1, arg2, ...)
小试牛刀
function method(val1, val2) { return this.a this.b val1 val2; const obj { a: 1, b: 2 console.log(method.call(obj, 3, 4)); // 1015.1.2 实现
实现一个call函数 将通过以下几个步骤
获取第一个参数 注意第一个参数为null或undefined时 this指向window 构建对象将对应函数传入该对象中获取参数并执行相应函数删除该对象中函数 消除副作用返回结果Function.prototype.myCall function (context, ...args) { // 获取第一个参数 注意第一个参数为null或undefined时 this指向window 构建对象 context context ? Object(context) : window; // 将对应函数传入该对象中 context.fn this; // 获取参数并执行相应函数 let result context.fn(...args); // 消除副作用 delete context.fn; // 返回结果 return result; // …… console.log(method.myCall(obj, 3, 4)); // 10
apply() 方法调用一个具有给定this值的函数 以及以一个数组 或类数组对象 的形式提供的参数。其返回值是指定this值和参数的函数的结果。call() 和 apply()的区别是call()方法接受的是参数列表 而apply()方法接受的是一个参数数组
基本用法
func.apply(thisArg, [argsArray])
小试牛刀
function method(val1, val2) { return this.a this.b val1 val2; const obj { a: 1, b: 2 console.log(method.apply(obj, [3, 4])); // 1015.2.2 实现
apply和call的区别主要是参数的不同 所以其实现步骤的call大体类似 如下所示
Function.prototype.myApply function (context, arr) { context context ? Object(context) : window; context.fn this; let result arr ? context.fn(...arr) : context.fun(); delete context.fn; return result; // …… console.log(method.myApply(obj, [3, 4])); // 1015.3 bind()15.3.1 基础
bind() 方法创建一个新的函数 在 bind() 被调用时 这个新函数的 this 被指定为 bind() 的第一个参数 而其余参数将作为新函数的参数 供调用时使用。该函数的返回值是一个原函数的拷贝 并拥有指定的this值和初始参数。
基本用法
function.bind(thisArg[, arg1[, arg2[, ...]]])
小试牛刀
function method(val1, val2) { return this.a this.b val1 val2; const obj { a: 1, b: 2 const bindMethod method.bind(obj, 3, 4); console.log(bindMethod()); // 1015.3.2 实现
实现一个bind函数相对较复杂一些 应该注意以下几点
能够改变this指向 返回的是一个函数 能够接受多个参数 支持柯里化形式传参 fun(arg1)(arg2) 获取到调用bind()返回值后 若使用new调用 当做构造函数 bind()传入的上下文context失效。Function.prototype.myBind function (context, ...args) { if (typeof(this) ! function ) { throw new TypeError( The bound object needs to be a function const self this; // 定义一个中装函数 const fNOP function() {}; const fBound function(...fBoundArgs) { // 利用apply改变this指向 // 接受多个参数 支持柯里化形式传参 // 当返回值通过new调用时 this指向当前实例 因为this是当前实例 实例的隐士原型上有fNOP的实例 fnop fnop instanceof fNOP为true return self.apply(this instanceof fNOP ? this : context, [...args, ...fBoundArgs]); // 将调用函数的原型赋值到中转函数的原型上 if (this.prototype) { fNOP.prototype this.prototype; // 通过原型的方式继承调用函数的原型 fBound.prototype new fNOP(); return fBound; }
相关文章
- vscode前端快速开发插件
- [转] 美团点评酒旅前端的技术体系
- 前端的设计模式 -- 混合模式
- 前端基础 -JQuery之 对样式的操作
- 打造高效前端工作环境 - tmux
- 前端面试第快速复盘,不标准的面试经验分享 (二)
- 前端面试题
- 【前端】JS耗时计算/时间转换/日期/本周/本月/格式化
- 对一个前端AngularJS,后端OData,ASP.NET Web API案例的理解
- Web前端-Vue.js必备框架(一)
- 前端学习 转(前端项目从0到1的感悟)
- jQuery结合Ajax实现简单的前端验证和服务端查询
- 关于前端JS走马灯(marquee)总结
- 前端面试题之---树形数据结构化
- 《Web前端工程师修炼之道(原书第4版)》——Web设计师是做什么的
- 【web前端初级课程】第六章 BOM编程的五大对象
- 前端性能优化:DocumentFragments或innerHTML取代复杂的元素注入
- 分享炫酷的前端页面随机二维码验证