JavaScript 中的 (0, fn)(args) 语法

36 阅读2分钟

JavaScript 中的 (0, fn)(args) 语法

最近看 ts 看到一段这样的代码

示例,在 tsx 文件中

import { h } from "preact";
const HelloWorld = () => <div>Hello</div>;

经过 tsc 编译后的代码

const preact_1 = require("preact");
const HelloWorld = () => (0, preact_1.h)("div", null, "Hello");

这里 tsx 中的 <div> 写法只是一个语法糖,实际表示调用 h("div", null, "Hello")

有意思的事情来了,明明可以是如 fn(args) 式的调用,生成的却是 (0, fn)(args) 式的调用。

为什么呢?

这里面蕴含的几个语法现象

  1. 逗号运算符

逗号运算符对其每个操作数(从左到右)进行求值,并返回最后一个操作数的值。

let x = 1;

x = (x++, x);

console.log(x); // 2

x = (2, 3);

console.log(x); // 3

  1. this 指向

如下示例代码,由于逗号运算符的存在, (0, foo.sayName) 返回的是对 foo.sayName 这个函数的引用。然后函数执行时,其内部的 this 指向已经变为了全局的上下文。

var foo = { 
    fullName: "Peter", 
    sayName: function() {
        console.log("My name is", this.fullName);
    } 
};
window.fullName = "Shiny";

foo.sayName();       // My name is Peter
(foo.sayName)();     // My name is Peter
(0, foo.sayName)();  // My name is Shiny

所以使用 (0, fn)(args) 的效果就是改变了函数 fn 内部的 this 指向,使其始终指向全局的上下文。

那么问题就变成了为什么要改变函数的 this 指向呢? 问了 deepseek ——

  1. 强制函数在全局上下文执行 - 切断原有的 this 绑定
  2. 避免意外的上下文绑定 - 确保函数行为可预测
  3. 代码压缩友好 - 比创建临时变量更简洁
  4. 函数式编程风格 - 强调"只是调用函数,不关心上下文"

总结一下,这种技巧在库函数、打包工具和框架代码中很常见,主要是为了确保函数的执行环境一致性。


参考