郑州招聘网站推广做闪图的网站
2025/12/31 10:46:39 网站建设 项目流程
郑州招聘网站推广,做闪图的网站,查询注册过的网站,开发一套网站多少钱#x1f525; 手撕call/apply/bind#xff1a;从ES6用法到手写实现#xff0c;吃透this指向核心 在JavaScript中#xff0c;this 指向的绑定是前端开发绕不开的核心知识点#xff0c;而 call、apply、bind 作为改变函数执行上下文的“三剑客”#xff0c;既是解决 this 丢… 手撕call/apply/bind从ES6用法到手写实现吃透this指向核心在JavaScript中this指向的绑定是前端开发绕不开的核心知识点而call、apply、bind作为改变函数执行上下文的“三剑客”既是解决this丢失问题的常用手段也是面试中考察JS基础的高频题。本文将从原生ES6用法、手写实现源码、核心差异深度对比三个维度结合实战源码案例带你彻底掌握这三个方法看完就能手写面试题一、核心共性本质都是改变this指向[!NOTE] 核心结论call、apply、bind的本质作用完全一致——修改函数执行时this的指向让函数能在指定的上下文环境中执行。比如对象内部的方法this原本指向对象本身而全局函数的this默认指向window浏览器环境通过这三个方法可强制改变这一规则// 基础原理示例this指向原对象constobj{name:测试1,name2:测试2,name3:测试3,say:function(){this.name2this.namethis.name3// this指向obj}};二、逐个拆解ES6用法 手写实现 核心逻辑下面针对每个方法先展示原生ES6用法再给出手写实现源码最后解析核心逻辑让你知其然也知其所以然。1. call参数列表传参立即执行① 原生ES6用法// ES6 原生call用法functionsay(){console.log(this.name)}constobj{name:Alice}say.call(obj)// 输出Alicecall接收第一个参数为绑定的this上下文后续为逗号分隔的参数列表调用后立即执行函数并返回结果。② 手写实现源码// 手写 myCall 实现Function.prototype.myCallfunction(receive,...args){// 处理默认上下文非严格模式下null/undefined指向windowreceivereceive||window// 将原函数挂载到目标对象上this指向原函数receive.fnthis// 执行函数并传递参数列表获取结果constresultreceive.fn(...args)// 清理临时属性避免污染目标对象deletereceive.fn// 返回函数执行结果与原生call行为一致returnresult}// 手写myCall测试案例functiontestFun(param1,param2){returnparam1this.aparam2}constobj1{a:测试1}console.log(testFun.myCall(obj1,测试0,测试2))// 输出测试0测试1测试2③ 核心逻辑解析[!TIP] 关键逻辑receive receive || window处理边界情况当传入的上下文为null/undefined时非严格模式下默认绑定windowreceive.fn this核心技巧——将原函数this指向调用myCall的函数挂载到目标对象上通过“对象.方法”调用让this指向目标对象delete receive.fn避免临时属性污染目标对象执行完立即删除...argsES6剩余参数接收所有逗号分隔的参数列表适配多参数场景。2. apply数组传参立即执行apply与call唯一的区别是参数传递形式执行时机和返回值完全一致。① 原生ES6用法apply接收第一个参数为绑定的this上下文第二个参数为数组/类数组对象调用后立即执行函数并返回结果。[!WARNING] 原生特性若第二个参数非数组且非undefined会抛出TypeError这是原生apply的核心特性。② 手写实现源码// 手写 myApply 实现Function.prototype.myApplyfunction(context,args){// 处理默认上下文contextcontext||window// 将原函数挂载到目标对象context.fnthisletresult// 核心处理数组参数if(!args){// 无参数时直接执行resultcontext.fn();}elseif(Array.isArray(args)){// 数组参数解构传递resultcontext.fn(...args)}else{// 非数组参数抛出类型错误符合原生行为thrownewTypeError(CreateListFromArrayLike called on non-object);}// 清理临时属性deletecontext.fn;returnresult}// 手写myApply测试案例constobj{name1:ceshi1}functiontestFun(param1,param2){returnparam1this.name1param2}console.log(testFun.myApply(obj,[测试2,测试3]))// 输出测试2ceshi1测试3③ 核心逻辑解析与myCall的核心差异args必须是数组通过Array.isArray()校验符合原生apply的参数规则context.fn(...args)将数组参数解构为参数列表本质是借用call的参数传递逻辑错误抛出严格校验参数类型保证手写实现与原生行为一致。3. bind参数分批传返回新函数不立即执行bind是三者中最特殊的一个核心差异是不立即执行函数而是返回绑定了this的新函数。① 原生ES6用法bind接收第一个参数为绑定的this上下文后续为可选的提前绑定参数调用后返回一个新函数只有执行新函数时才会触发原函数执行且支持参数分批传递柯里化特性。② 手写实现源码// 手写 myBind 实现Function.prototype.myBindfunction(context,...bindArgs){constselfthis;// 保存原函数引用避免this丢失// 返回新函数核心不立即执行functionboundFn(...callArgs){// 关键判断是否作为构造函数调用// new调用时this instanceof boundFn 为 truethis 指向实例// 否则this 指向绑定的 contextconstthisArgthisinstanceofboundFn?this:context;// 执行原函数合并绑定参数调用参数通过apply传递returnself.apply(thisArg,bindArgs.concat(callArgs));}// 继承原函数的prototype保证new实例能访问原原型方法boundFn.prototypeObject.create(self.prototype);returnboundFn;};// 手写myBind测试案例functionsay(greeting,punctuation){console.log(greeting, this.namepunctuation);}constperson{name:Alice};// 绑定this和第一个参数返回新函数不执行constboundSaysay.myBind(person,Hello);boundSay(!);// 执行新函数输出Hello, Alice!// 特殊场景作为构造函数使用functionPerson(name){this.namename;}Person.prototype.sayNamefunction(){console.log(this.name);};constBoundPersonPerson.myBind({name:Bob});constpnewBoundPerson(Charlie);p.sayName();// 输出Charliethis指向实例而非绑定的对象③ 核心逻辑解析[!TIP] 核心难点const self this保存原函数引用避免后续嵌套函数中this指向丢失返回新函数boundFn核心差异——不立即执行而是返回绑定后的新函数bindArgs.concat(callArgs)支持参数分批传递绑定阶段传一部分调用阶段传一部分this instanceof boundFn关键判断——当新函数被new调用时this指向实例而非绑定的context符合原生bind的构造函数特性boundFn.prototype Object.create(self.prototype)继承原函数的原型链保证new实例能访问原函数的原型方法。三、深度对比三者核心差异补充版特性callapplybind参数形式逗号分隔的参数列表单个数组/类数组参数支持分批传参绑定调用阶段执行时机立即执行立即执行不立即执行返回新函数返回值函数执行结果函数执行结果绑定this的新函数构造函数场景无特殊处理极少用无特殊处理极少用自动适配this指向实例手写源码核心差异直接解构剩余参数传参校验数组参数后解构传参需返回新函数、合并参数、适配new原生场景适配多独立参数且需立即执行参数为数组且需立即执行需提前绑定this延迟执行补充源码层面的核心区别call vs apply手写源码的唯一差异在参数处理逻辑——call直接用剩余参数...args接收列表apply需校验数组参数后解构bind vs call/applybind的手写源码更复杂多了三个核心逻辑返回新函数而非立即执行合并“绑定阶段参数”和“调用阶段参数”适配构造函数场景保证new调用时this指向实例。总结 call和apply核心差异仅在参数形式均立即执行并返回函数结果bind核心差异是不立即执行返回新函数支持分批传参且适配构造函数场景手写实现的核心逻辑是通过“函数挂载到目标对象→调用函数→清理挂载”改变thisbind需额外处理新函数、参数合并、new适配。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询