Object spread 语法从不抛出错误吗?
Does the Object spread syntax never throw an error?
我注意到 Object Spread 语法对它可以接受的值类型非常宽松:
console.log({ ...true });
console.log({ ...false });
console.log({ ...0 });
console.log({ ...42 });
console.log({ ...-1 });
console.log({ ...NaN });
console.log({ ...'batman' });
console.log({ .../\w+[0-9a-fA-F]?/ });
console.log({ ...['foo', 'bar', 42] });
console.log({ ...undefined });
console.log({ ...false });
console.log({ ...Symbol('hmm') });
console.log({ ...Promise.resolve('resolved') });
console.log({ ...Promise.reject('rejected') });
是否有类型、class 或值在对象字面量中传播时无效(即抛出任何类型的错误)?当然,不包括未兑现的拒绝承诺。
不,在对象字面量中传播时没有无效的表达式,当然前提是对该表达式本身的求值不会引发错误。
从ECMAScript规范中我们可以看出是这样的:
在12.2.6 Object Initializer处,我们找到对象字面量展开语法的语法定义:
PropertyDefinition:
...
AssignmentExpression[+In, ?Yield, ?Await]
一个 AssignmentExpression 表示所有可能的表达式(包括赋值),逗号运算符除外,这实际上意味着如果您希望将逗号解释为,则需要使用括号逗号运算符而不是对象文字的逗号分隔符(参见 12.15 Assignment Operators and 12.16 Comma Operator)。
评估程序在12.2.6.8 Runtime Semantics: PropertyDefinitionEvaluation中指定:
PropertyDefinition:...
AssignmentExpression
- Let exprValue be the result of evaluating AssignmentExpression.
- Let fromValue be ? GetValue(exprValue).
- Let excludedNames be a new empty List.
- Return ? CopyDataProperties(object, fromValue, excludedNames).
我们假定表达式本身不会在求值过程中抛出异常,这意味着上述 GetValue 过程将成功无错。然后我们可以检查 CopyDataProperties 在 7.3.25 CopyDataProperties 中做了什么。重要的步骤是:
- If source is
undefined
or null
, return target.
- Let from be ! ToObject(source).
现在,当 source 是 null
或 undefined
时,ToObject 会抛出异常,但这两种情况已经在上一步。所有其他原始值都装箱到包装器对象中(参见 7.1.18 ToObject)。
最后,CopyDataProperties 还有一个可能抛出的步骤:
- c. 2. ii. Perform ! CreateDataPropertyOrThrow(target, nextKey, propValue).
但是只有当要设置的 属性 已经存在且不可配置,或者目标对象不可扩展时才会抛出(参见 7.3.7 CreateDataPropertyOrThrow and 7.3.5 CreateDataProperty)。但是这种情况不会出现在对象字面量中。它们可能发生在扩展对象的较大评估中,但此类错误与扩展语法无关特别是.
我注意到 Object Spread 语法对它可以接受的值类型非常宽松:
console.log({ ...true });
console.log({ ...false });
console.log({ ...0 });
console.log({ ...42 });
console.log({ ...-1 });
console.log({ ...NaN });
console.log({ ...'batman' });
console.log({ .../\w+[0-9a-fA-F]?/ });
console.log({ ...['foo', 'bar', 42] });
console.log({ ...undefined });
console.log({ ...false });
console.log({ ...Symbol('hmm') });
console.log({ ...Promise.resolve('resolved') });
console.log({ ...Promise.reject('rejected') });
是否有类型、class 或值在对象字面量中传播时无效(即抛出任何类型的错误)?当然,不包括未兑现的拒绝承诺。
不,在对象字面量中传播时没有无效的表达式,当然前提是对该表达式本身的求值不会引发错误。
从ECMAScript规范中我们可以看出是这样的:
在12.2.6 Object Initializer处,我们找到对象字面量展开语法的语法定义:
PropertyDefinition:
...
AssignmentExpression[+In, ?Yield, ?Await]
一个 AssignmentExpression 表示所有可能的表达式(包括赋值),逗号运算符除外,这实际上意味着如果您希望将逗号解释为,则需要使用括号逗号运算符而不是对象文字的逗号分隔符(参见 12.15 Assignment Operators and 12.16 Comma Operator)。
评估程序在12.2.6.8 Runtime Semantics: PropertyDefinitionEvaluation中指定:
PropertyDefinition:
...
AssignmentExpression
- Let exprValue be the result of evaluating AssignmentExpression.
- Let fromValue be ? GetValue(exprValue).
- Let excludedNames be a new empty List.
- Return ? CopyDataProperties(object, fromValue, excludedNames).
我们假定表达式本身不会在求值过程中抛出异常,这意味着上述 GetValue 过程将成功无错。然后我们可以检查 CopyDataProperties 在 7.3.25 CopyDataProperties 中做了什么。重要的步骤是:
- If source is
undefined
ornull
, return target.- Let from be ! ToObject(source).
现在,当 source 是 null
或 undefined
时,ToObject 会抛出异常,但这两种情况已经在上一步。所有其他原始值都装箱到包装器对象中(参见 7.1.18 ToObject)。
最后,CopyDataProperties 还有一个可能抛出的步骤:
- c. 2. ii. Perform ! CreateDataPropertyOrThrow(target, nextKey, propValue).
但是只有当要设置的 属性 已经存在且不可配置,或者目标对象不可扩展时才会抛出(参见 7.3.7 CreateDataPropertyOrThrow and 7.3.5 CreateDataProperty)。但是这种情况不会出现在对象字面量中。它们可能发生在扩展对象的较大评估中,但此类错误与扩展语法无关特别是.