call、apply 功能介绍
call 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数。
call 和 apply 的区别:传入参数的格式不同,call 正常逐个传入 apply 接受一个参数数组。
注意点:
- 将 this 绑定为指定对象。
 - 如果传入 null、undefined 将视为传入 window 对象,如果是其他基本类型将其变为对应的包装对象。
 - 执行的函数可以有返回值。
 
// 用法var value = 2;var obj = {value: 1}function bar(name, age) {console.log(this.value);return {value: this.value,name: name,age: age}}bar.call(null); // 2console.log(bar.call2(obj, 'kevin', 18));// 1// Object {// value: 1,// name: 'kevin',// age: 18// }
模拟实现
Function.prototype.call = function (context) {// 判断是否为 null 或 undefinedif(context === null || context === undefined) {context = window} else {// 将其他基本的数据类型转换为对应的包装对象context = Object(context)}context.fn = this;var args = [];// 拿到传入的参数for(var i = 1, len = arguments.length; i < len; i++) {args.push('arguments[' + i + ']');}// 因为参数是字符串,所以用 eval 执行一下var result = eval('context.fn(' + args +')');// 删除不留痕迹delete context.fn// 放回函数执行的结果return result;}
同样道理 apply 也差不多
Function.prototype.apply = function (context, arr) {// 判断是否为 null 或 undefinedif(context === null || context === undefined) {context = window} else {// 将其他基本的数据类型转换为对应的包装对象context = Object(context)}context.fn = this;var result;// 没有参数直接执行if (!arr) {result = context.fn();}else {var args = [];for (var i = 0, len = arr.length; i < len; i++) {args.push('arr[' + i + ']');}result = eval('context.fn(' + args + ')')}delete context.fnreturn result;}
参考:
[1] Javascript 深入之 call 和 apply 的模拟实现。
[2] MDN
