Function.prototype.apply.call 客官°小女子只卖身不卖艺 2022-05-23 07:19 145阅读 0赞 今天在读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或者反之,因为都在原型链上,这很容易理解。 [参考文章][Link 1] [call的定义][call] [apply的定义][apply] [Link 1]: http://www.jb51.net/article/39456.htm [call]: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call [apply]: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
还没有评论,来说两句吧...