欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js call和apply方法

程序员文章站 2024-02-28 21:06:07
...

MDN上的介绍是:apply() 方法调用一个具有给定this值的函数,以及作为一个数组(或类似数组对象)提供的参数。call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
call和apply都是为了改变某个函数运行时的上下文而存在的,即为了改变函数体内部this的指向。JavaScript 的一大特点是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。

var numbers = [5, 6, 2, 3, 7];
var max = Math.max.apply(null, numbers);  // 参数数组
console.log(max); // 7
// call方法:
var max1 = Math.max.call(null, 5, 6, 2, 3, 7);

console.log(max1); // 7

先看语法:
func.apply(thisArg, [argsArray])

第一个参数thisArg, 可选。
即在 func 函数运行时使用的 this 值。在非严格模式下,指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。

第二个参数argsArray,可选。
一个数组或类数组对象。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。

函数返回值是调用有指定this值和参数的函数的结果。
我们可以模拟实现:

Function.prototype.call2 = function(context) {
	var context = Object(context) || window; // 为null或undefined则指向window
    // 首先要获取调用call的函数,用this可以获取
    context.fn = this;
    var result = context.fn(); // 可能会有返回结果
    delete context.fn;
    return result;
}

但call 方法还可以传参数, 我们先使用es6语法进行模拟:

Function.prototype.call2 = function(context) {
	var context = Object(context) || window; // 为null或undefined则指向window
    // 首先要获取调用call的函数,用this可以获取
    context.fn = this;
    var result;
    // 判断是否有第二个参数
    if(arguments[1]){
    	result = context.fn(...arguments[1]);
    }else {
    	result = context.fn();
	}
    delete context.fn;
    return result;
}

不使用es6方法的话,我们可以使用eval函数,因为我们需要得到类似这种"obj.fn(args1,args2,args3)" 这样的 ,通过将所有参数拼成字符串然后eval执行

Function.prototype.call2 = function(context) {
	var context = Object(context) || window; // 为null或undefined则指向window
    // 首先要获取调用call的函数,用this可以获取
    context.fn = this;
    var args = [];
    for (var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }
    var result = eval('context.fn(' + args +')');
    delete context.fn;
    return result;
}

参考资料: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
https://github.com/mqyqingfeng/Blog/issues/11
https://segmentfault.com/q/1010000009688328

相关标签: js call apply