什么是中间值?

Ade*_*lin 11 javascript

今天我完全碰到了这个问题:Uncaught TypeError :(中间值)(...)不是函数

所以是的,在适当的位置放置分号后,它不再抛出该错误.但是,我从来不知道javascript中有这样的概念(intermediate value).

显然,您可以使用以下代码生成该错误的类似变体:

[myFunc] = function(someVar){
	
	console.log(someVar);
	return 7;
}();

//error thrown: (intermediate value) is not a function or its return value is not iterable
Run Code Online (Sandbox Code Playgroud)

如果你命名这个函数,它不再是intermediate:

function hi(){return undefined}

[a] = hi(); 

// error thrown: hi is not a function or its return value is not iterable
Run Code Online (Sandbox Code Playgroud)

我理解它指的是中间的东西,但在这种情况下我们有一个匿名函数,并且有方法来确定函数是否是匿名的,因此错误消息可能更明确一些.

搜索js mozilla mdn我找到了这个页面,Array.from可以找到"中间数组"的概念:

更清楚的Array.from(obj, mapFn, thisArg)Array.from(obj).map(mapFn, thisArg),除了不创建中间数组之外,具有相同的结果.

但除了这里和那里的信息之外,还不清楚中间值是什么.

对此有官方定义吗?

T.J*_*der 11

"中间值"只是在表达式内生成的值,该表达式不是表达式的最终值.在a = (b * c) + d的结果b * c是在右手侧表达式的中间值.

是的,在这种特定情况下,错误消息可能会说"(匿名函数)不是函数或其返回值不可迭代".但是,并非所有中间值都是匿名函数.V8的实施者只是选择使用通用错误消息.(SpiderMonkey [在Firefox中]使用相同的术语,但不同的消息.)

对此有官方定义吗?

规范在这里使用术语"中间结果" ,意思是与"中间值"(对我的眼睛)基本相同:

6.2 ECMAScript规范类型

规范类型对应于在算法中用于描述ECMAScript语言构造和ECMAScript语言类型的语义的元值.规范类型包括参考,列表,完成,属性描述符,词汇环境,环境记录和数据块.规范类型值是规范伪像,其不一定对应于ECMAScript实现中的任何特定实体.规范类型值可用于描述ECMAScript表达式评估的中间结果,但这些值不能存储为对象的属性或ECMAScript语言变量的值.

(我的重点)


请注意,除了为函数指定名称之外,您的代码示例并不相同.其中一个尝试迭代该值7.另一个尝试迭代该值undefined.它与V8的错误消息无关,但它对SpiderMonkey有效.让我们将苹果与苹果进行比较,删除无关紧要,并声明我们的变量:

"use strict";

var myFunc;

try {
  [myFunc] = function(){
    return 7;
  }();
} catch (e) {
  console.error(e.message);
}

try {
  [myFunc] = function hi(){
    return 7;
  }();
} catch (e) {
  console.error(e.message);
}

try {
  function hi(){
    return 7;
  }
  [myFunc] = hi();
} catch (e) {
  console.error(e.message);
}
Run Code Online (Sandbox Code Playgroud)

  • 你可能会认为 JS 在显示该错误消息时会确切地知道“中间值”是什么...... (2认同)
  • 说真的,由于有明确的执行顺序,并且一次对表达式的每个部分进行评估,我发现这种错误的存在很奇怪。我仍然不明白为什么我不只看到“未定义”而不是“中间值” (2认同)
  • 再一次,你假设很多.JavaScript并不是一行一行地准确评估所有内容.它将预处理脚本,然后开始执行它.您的`var num = 7`实际上包括*三步*甚至执行该行.它被定义,因此`num`作为一个概念存在,然后它被初始化,所以它可以*使用*,最后它被赋值为'7`.如果理论上在定义之后但在初始化之前有`num> 10`你也会得到一个错误信息,也可能说`num不是数字'(它甚至还没有'未定义')`或者不大于10` - 它不是. (2认同)

ell*_*kie 5

当使用可选链时也会提到:

const b = undefined;
const a = [...b?.c];  // "Uncaught TypeError: 
                      //  (intermediate value) is not iterable"
Run Code Online (Sandbox Code Playgroud)

但不是在这里:

const b = undefined;
const a = [...b.c];  // "Uncaught TypeError: 
                     //  Cannot read properties of undefined (reading 'c')"
Run Code Online (Sandbox Code Playgroud)

我的猜测是,引擎不会报告最内层表达式的问题,而是首先抛出与最外层表达式相关的错误。在那个级别,可迭代已经是错误的,并且没有正确命名它,而是使用“中间值”的通用名称来调用它。

我的环境:

  • 谷歌浏览器:108.0.5359.98(官方版本)(x86_64)
  • JavaScript:V8 10.8.168.21
  • 操作系统:macOS 版本 12.6.1