We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
关于这块真的是基础的基础,曾经在遇到的时候一次又一次的跳过,包括用一些其他方式给解决了,但是若想深入,甚至看各种源码的时候,也是绕不开的知识点,必须好好学习。
call,apply,bind 都可以改变函数的执行上下文,也就是函数运行时 this 的指向。
call
apply
bind
区别在于,call 和 apply 改变了函数的执行上下文后会执行该函数,而 bind 不会执行该函数而是返回一个新函数。在参数的处理上,call 和 apply 的第一个参数都是函数运行时的 this 值,区别在于,call 方法接受的是参数列表,apply 接受的是一个参数数组或类数组对象。
apply 接受一个函数运行时的 this 值和一个参数数组或类数组对象,与 call 的区别在于对参数处理不同。
手写实现:
Function.prototype.apply = function(context, args) { // 对this的判断 if (typeof this !== "function") { throw new TypeError("Error") } // 可对context的判断再做优化 context = context || window // 可对第二参数进行容错,数组或者类数组 args = args || [] // 给context新增一个独一无二的属性以免覆盖原有属性 const key = Symbol() context[key] = this const result = context[key](...args) // 带走产生的副作用 delete context[key] return result }
call 接受一个函数运行时的 this 值和一个参数列表,如果不指定第一个参数时,默认执行上下文为 window,改变 this 指向后,需要让新对象可以执行该函数,并能接受参数。
//传递参数从一个数组变成逐个传参了,不用...扩展运算符的也可以用arguments代替 Function.prototype.call = function (context, ...args) { //这里默认不传就是给window,也可以用es6给参数设置默认参数 context = context || window; args = args ? args : []; //给context新增一个独一无二的属性以免覆盖原有属性 const key = Symbol(); context[key] = this; //通过隐式绑定的方式调用函数 const result = context[key](...args); //删除添加的属性 delete context[key]; //返回函数调用的返回值 return result; }
bind 接受一个函数运行时的 this 值和一个参数列表,返回一个新函数。
Function.prototype.bind = function (context, ...args) { const fn = this args = args ? args : [] return function newFn(...newFnArgs) { if (this instanceof newFn) { return new fn(...args, ...newFnArgs) } return fn.apply(context, [...args,...newFnArgs]) } }
Function.prototype.bind = function (objThis, ...params) { const thisFn = this; // 存储源函数以及上方的params(函数参数) // 对返回的函数 secondParams 二次传参 let fToBind = function (...secondParams) { const isNew = this instanceof fToBind // this是否是fToBind的实例 也就是返回的fToBind是否通过new调用 const context = isNew ? this : Object(objThis) // new调用就绑定到this上,否则就绑定到传入的objThis上 return thisFn.call(context, ...params, ...secondParams); // 用call调用源函数绑定this的指向并传递参数,返回执行结果 }; if (thisFn.prototype) { // 复制源函数的prototype给fToBind 一些情况下函数没有prototype,比如箭头函数 fToBind.prototype = Object.create(thisFn.prototype); } return fToBind; // 返回拷贝的函数 };
The text was updated successfully, but these errors were encountered:
JavaScript中call方法的手动实现,与多个call连用引发的思考._个人文章 - SegmentFault 思否
Sorry, something went wrong.
No branches or pull requests
区别
call
,apply
,bind
都可以改变函数的执行上下文,也就是函数运行时 this 的指向。区别在于,
call
和apply
改变了函数的执行上下文后会执行该函数,而bind
不会执行该函数而是返回一个新函数。在参数的处理上,call
和apply
的第一个参数都是函数运行时的 this 值,区别在于,call
方法接受的是参数列表,apply
接受的是一个参数数组或类数组对象。apply
apply
接受一个函数运行时的 this 值和一个参数数组或类数组对象,与call
的区别在于对参数处理不同。手写实现:
call
call
接受一个函数运行时的 this 值和一个参数列表,如果不指定第一个参数时,默认执行上下文为 window,改变 this 指向后,需要让新对象可以执行该函数,并能接受参数。手写实现:
bind
bind
接受一个函数运行时的 this 值和一个参数列表,返回一个新函数。手写实现:
参考资料
The text was updated successfully, but these errors were encountered: