当前位置 : 主页 > 大数据 > 区块链 >

Function.prototype.apply.call

来源:互联网 收集:自由互联 发布时间:2021-06-22
今天在读cw_logger源码的时候,看到这么一个方法: Function .prototype .apply .call 顿时,觉得难道还能这么调用。为什么? 1. 先来看看上下文 if (context === MyLogger .WARN console .warn ) { hdlr = consol

今天在读cw_logger源码的时候,看到这么一个方法:

Function.prototype.apply.call

顿时,觉得难道还能这么调用。为什么?


1. 先来看看上下文

if (context === MyLogger.WARN && console.warn) {
    hdlr = console.warn;
  } else if (context === MyLogger.ERROR && console.error) {
    hdlr = console.error;
  }
}

invokeConsoleMethod(hdlr, messages) {
    let moduleStr = "[" + this.logOwner + "]";
    Function.prototype.apply.call(hdlr, console, [moduleStr, messages]);
}

参数说明:

hdlr : 是外部传进来的函数

message : 提示信息

其他说明 :

console , 就是浏览器的console


2. 再看call

先来复习定义:

fun.call(thisArg, arg1, arg2, ...)

thisArg

在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。

arg1, arg2, …

指定的参数列表。

PS:

fun.apply(obj,args)等价于obj.fun(args),这一步是重点,必须理解。

call接受的是一个参数列表。

(Function.prototype.apply).call(hdlr, console, [moduleStr, messages]);

hdlr 将函数运行的上下文,指向了console.error或者console.warn。

相当于:

hdlr.apply(console, [moduleStr, messages]);

3.再看apply

先来看看apply的定义

func.apply(thisArg, [argsArray])

thisArg

可选的。在 func 函数运行时使用的 this 值。需要注意的是,使用的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的包装对象。

argsArray

可选的。++==一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数==++。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。

举个例子:

var numbers = [5, 6, 2, 3, 7];

/* using Math.min/Math.max apply */
var max = Math.max.apply(null, numbers);

于是乎:

hdlr.apply(console, [moduleStr, messages]);

相当于:

hdlr(moduleStr, messages);

就相当于:

console.error(moduleStr, messages);

4.来道考题

var b = Function.prototype.call.apply(function(a){return a;}, [0,4,3]);
alert(b); 


结果:

b = 4;

按照上面的解释,apply的代码会变成这样:

b = (function(a){return a;}).call(0,4,3)

结果:

b = 4

5.总结

不管是call在前,还是apply在前。只要是以Function.prototype.call形式被调用,他们都会将函数的上下文指向第一个参数。如果后面没有更改,那么就会一直指向那个上下文。

当然如果第一个参数是一个指定的值或者null、undefined,而不是一个具体的对象,那么上下文环境不发生改变。

至于call后面还可以调用apply或者反之,因为都在原型链上,这很容易理解。

参考文章

call的定义

apply的定义

网友评论