新人 JavaScript 求助语法问题

2022-05-26 10:29:47 +08:00
 fenglala
function sleepPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("promise")
        }, 1000)
    })
}

sleepPromise() // 这里没有分号

    (function () {
        console.log("hhh")
    })()

为啥调用 sleepPromise()的时候不加分号,就会跑不起来,加了分号就可以了

PS C:\Users\lala\Downloads> node c.js
C:\Users\lala\Downloads\c.js:11
    (function () {
    ^

TypeError: sleepPromise(...) is not a function
    at Object.<anonymous> (C:\Users\lala\Downloads\c.js:11:5)
    at Module._compile (node:internal/modules/cjs/loader:1105:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

加了分号之后

function sleepPromise() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("promise")
        }, 1000)
    })
}

sleepPromise(); // 这里有分号

    (function () {
        console.log("hhh")
    })()
PS C:\Users\lala\Downloads> node c.js
hhh
promise

我会 C ,但是不会 JavaScript ,求指教,感谢!

2717 次点击
所在节点    JavaScript
26 条回复
wangtian2020
2022-05-26 15:09:07 +08:00
sleepPromise()(function () {console.log("hhh")})()

sleepPromise()(/* something */)()

如果你用 prettier 格式化一下,他就会变成这个样子

很容易看出问题所在。根本原因是 JavaScript 语法的冲突
ryougifujino
2022-05-26 15:17:18 +08:00
以前我也是坚定的分号党,其实无分号反而更简洁,后来成为了无分号党。只需要稍微注意一下就行了。简单来说就是“一行开头是括号或者方括号的时候加上分号就可以了”
参考:
JavaScript 语句后应该加分号么? - 尤雨溪的回答 - 知乎
https://www.zhihu.com/question/20298345/answer/49551142
ryougifujino
2022-05-26 15:31:14 +08:00
@ryougifujino #22 append 一下,还得加一个字符串模板开头。https://zhuanlan.zhihu.com/p/24612490
tutou
2022-05-26 16:40:09 +08:00
所以一般 js 插件自执行函数自己会加个分号
weiwoxinyou
2022-05-26 20:16:22 +08:00
@fenglala op 的这个例子不是很符合你的原意,这个例子之所以能运行是因为符合了编译器的解析规则,题干中的代码本质上是未插入分号导致了
f()
(fx())()
被解析成了 f()(fx())(), 在编译器解析你的代码时,从左向右读取,也就是说编译器的解析顺序是
f() => // 1
f()(fx()) => // 2
f()(fx())() // 3
在第一步中,你的函数本正确执行了,但是在第二步中,编译器认为第一步的结果是一个函数,后面括号内的是函数传递的参数,但是由于第一步运行完没有返回函数,因此第一步的返回值被定义为空,显然空值并不是函数,于是产生报错,产生报错后,错误向外层抛出,而顶层调用函数名叫 sleepPromise ,于是,该报错为 sleepPromise is not a function.

op 的例子之所以能执行,是因为你返回了一个函数,这个函数里面可以被递归调用,递归返回的也是一个函数,刚好满足了被编译器解析的对一个函数进行 3 次调用的规则,本质上是将返回的匿名函数作为参数传递给了调用者,JS 里面与这种调用很相似调用的叫函数柯里化
fenglala
2022-05-26 21:14:01 +08:00
@weiwoxinyou 谢谢你的详细讲解!又学到一个之前都没听说过的新东西 函数柯里化

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/855376

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX