手写JavaScript中的call()、apply()和bind()

编程入门 行业动态 更新时间:2024-10-27 08:29:17

手写JavaScript中的<a href=https://www.elefans.com/category/jswz/34/1771072.html style=call()、apply()和bind()"/>

手写JavaScript中的call()、apply()和bind()

call()

定义:

call()为函数中的一个方法, 其参数为一个指定的this值,以及一个参数列表

语法:

fn.call(thisArg, a,b,c)
  • thisArg:在fu函数运行时指定this的值,如果指定为null或者undefined会指向全局对象,浏览器中就是window对象。
  • a,b,c:参数列表,作为参数传给fu函数

也就是说call能使fn函数中的this指向其第一个参数thisArg对象

const obj1 = {name: 'ahua',getName(h1,h2) {console.log(`我叫${this.name},喜欢${h1}和${h2}`); }
};const obj2 = {name: '阿花'
};
obj1.getName.call(obj2,'读书','看报')
// 我叫阿花,喜欢读书和看报

手写call()

  1. call支持多个参数,可能一个,可能一个也没有
  2. 多参数时要把thisArg外的参数传给扩展方法
  3. 结束后要把扩展的自定义函数删除
Function.prototype.mycall = function(context){// context 就是上面call的参数obj2,因为只有一个形参,所以后面两个参数会被忽略// 如果没有指定this,this指向windowvar context = context || window;// 调用mycall的是obj1对象的getName函数,所以this指向getName函数// 这个表达式的意思就是在obj2中定义一个fn去复制getName函数context.fn = this;var args = [];// Javascrip中的函数都有一个Arguments对象实例arguments(类数组),它引用着函数的实参arguments,arguments[num]和其参数一一对应。// 将mycall中第一个参数thisArg对象(obj2)移除,剩余的('读书','看报')作为fn的参数for (var i = 1, len = arguments.length; i < len; i++) {args.push(arguments[i]);}const result = context.fn(...args);// 删除fn方法delete context.fn;return result;}obj1.getName.mycall(obj2,'读书','看报')// 我叫阿花,喜欢读书和看报

apply()

定义:

apply() 为函数的一个方法, 其参数为一个指定的this值,以及一个数组(或类似数组的对象)

语法:

fu.apply(thisArg, [argsArray])
  • thisArg:在fu函数运行时指定this的值,如果指定为null或者undefined会指向全局对象,浏览器中就是window对象。
  • arrgsArray:一个数组或者类数组对象,作为参数传给fu函数

apply也能使函数中的this指向其第一个参数thisArg对象

const obj1 = {name: 'ahua',getName(x,y) {console.log(`我叫${this.name},喜欢${x}和${y}`); }
};const obj2 = {name: '阿花'
};
obj1.getName.apply(obj2,['吃饭','睡觉']) // 我叫阿花,喜欢吃饭和睡觉

手写apply

apply不同的就是第二个参数变成了数组

Function.prototype.myapply = function(content) {// 如果没有传或传的值为空对象 context指向windowif (typeof context === "undefined" || context === null) {context = window}let args = [...arguments].slice(1) //效果同mycall中的for循环// 给obj2添加一个方法fn(复制this) 因为是getName调用的myapply所以this指向getNamecontent.fn = this // arguments引用着myapply的两个参数,第一个是obj2,第二个是['吃饭','睡觉']const result = content.fn(arguments[1][0],arguments[1][1])//执行fndelete content.fn //删除方法return result}  obj1.getName.myapply(obj2,['吃饭','睡觉'])// 我叫阿花,喜欢吃饭和睡觉

bind()

用法和call类似,不过bind()会创建一个新的函数,需要再次进行调用

function a(x, y, z){return this.name + '喜欢' + x + '、' + y + '和' + z;
}var b = {name : '阿花'};
a.getName.bind(b,'读书','看报')('滑板')
// 阿花喜欢读书、看报和滑板	

手写bind()

  1. 函数调用
  2. 改变this
  3. 返回一个绑定this的函数
  4. 接收多个参数
  5. 支持柯里化形式传参 fn(1)(2)(3)

代码实现

Function.prototype.mybind = function(context){if (typeof context === "undefined" || context === null) {context = window}// a.mybind(b,参数1,参数2)(参数3)  context是b args是通过arguments获取参数1和参数2  return函数中的参数是参数3var args = [...arguments].slice(1);// args['读书','看报']// 保存this,因为如果后面进入return函数后,this的指向会改变var self = this;// 调用bind后返回一个this指向第一个参数(b)的函数return function(){// mybind(b, '读书', '看报')是调用自定义的mybind方法,// a.mybind(b, '读书', '看报')('滑板')是继续调用的mybind中return的函数,所以return中的函数参数为('滑板')// 将类数组转换为数组  innerArgs ['滑板']var innerArgs = [...arguments];console.log(arguments)// 实现函数curry:把接受多个参数的函数变换成接受一个单一参数的函数// 即:将bind(thisArg,参数1,参数2)(参数3) 中的参数1,参数2,参数3合并为一个参数作为apply的第二个参数var finalArgs = args.concat(innerArgs);//finalArgs ['读书','看报' ,'滑板']// 用apply是因为传入的第二个参数为数组return self.apply(context, finalArgs);}
}
// 测试结果
function a(x, y, z){return this.name + '喜欢' + x + '、' + y + '和' + z;
}var b = {name : '阿花'};console.log(a.mybind(b, '读书', '看报')('滑板'));

更多推荐

手写JavaScript中的call()、apply()和bind()

本文发布于:2024-03-12 12:19:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1731494.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:call   JavaScript   bind   apply

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!