javascript_冷知识之_(0, function)(param)

(0 , function)(param) 究竟是什么?

最近在读一些 loader 的源码,发现有许多摸不着头脑的地方,其中一点是有许多函数在调用时,都采用了(0, function)(param) 的形式调用。如

(0, _schemaUtils.default)(_options.default, options, {
    name: 'CSS Loader',
    baseDataPath: 'options'
  });

网上资料

刚开始很不理解,在 stackoverflow 上寻找答案,大致了解这种写法的作用是强制改变 this 的指向。
What is the meaning of this code (0, function) in javascript [duplicate]
有几种说法,不过基本上可以理解为改变了 this 的指向。

实践出真知

那么它的 this 指向究竟被改成了啥?带着这个疑问,写下如下代码并在两种环境下运行(node / window)

const dog = {
    run() {
        console.log(this);
        console.log('I\'m running');
    }
};
dog.run();
(0, dog.run)();

node

{ run: [Function: run] }
I'm running
Object [global]
I'm running

window
run in window
原来如此,(0, function)(param) 会将 this 指向全局对象,也就是 window 或者 global。
而且有趣的是,不光是 0 ,你传随意值,0可能是为了理解和方便。
在这里插入图片描述

本质

其本质是 js逗号操作符
逗号操作符 对它的每个操作对象求值(从左至右),然后返回最后一个操作对象的值。
如:

let x = 1;

x = (x++, x);

console.log(x);
// expected output: 2

x = (2, 3);

console.log(x);
// expected output: 3

那么回到这段代码中,进行调用时则可以等价于:

const dog = {
    run() {
        console.log(this);
        console.log('I\'m running');
    }
};
dog.run();
(0, dog.run)();
(0, dog.run)();

// 左边先用逗号操作符从左到右执行并取值,最终返回
dog.run: function run() {
	console.log(this);
	console.log('I\'m running');
}
// 等价于如下,此时的 this 就是 全局对象 了
(function run() {
	console.log(this);
	console.log('I\'m running');
})();

事后反思

为什么源码要用这种 (0, function)(param) 方式去绑定 this,而不是 function.call()/apply() 的形式呢?
那是因为这些源码中有时会修改 prototype ,将 call/apply 指向成自己的函数,甚至改变prototype 的指向,这样就会导致原型链上方法不可用,那就只好(0, function)(param ) 了。我理解这有点亡羊补牢的感觉。。。
了解一下就好了,实际开发中还是不要修改原型链,避开使用这种小众化的语法。
不得不说,源码真让人摸不着头脑


版权声明:本文为qq_39446719原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。