使用对象解构赋值时,为啥将属性“名称”转换为字符串? [复制]

Posted

技术标签:

【中文标题】使用对象解构赋值时,为啥将属性“名称”转换为字符串? [复制]【英文标题】:When using object destructuring assignment, why is a property "name" cast to string? [duplicate]使用对象解构赋值时,为什么将属性“名称”转换为字符串? [复制] 【发布时间】:2017-11-08 07:34:20 【问题描述】:

给定

let obj = name: 1;
console.log(typeof obj.name, obj.name); // `"number"`, `1`

在对象解构赋值中使用var 时,为什么name 标识符会转换为字符串?

let obj = name: 1;
var name = obj; 
console.log(name, typeof name); // `1` `string`

但不使用letconst

let obj = name: 1;
let name = obj; 
console.log(name, typeof name);

我们可以通过定义不同的标识符来避免这种意外结果

let obj = name: 1;
var name:_name = obj; 
console.log(_name, typeof _name);

虽然好奇 var 在浏览器环境中返回的结果与 letconstname 标识符不同?

【问题讨论】:

这种行为跨引擎是否一致? @torazaburo 是的。 *nix 32 位的 chromium 58 和 firefox 53 产生相同的结果。没有在 mac 上的 safari 或 *indows 上的 edge 尝试过。 @torazaburo 推测与window.name 相关。虽然为什么 varletconst 的结果不同? 【参考方案1】:

此行为由执行代码的范围定义。

name 指的是window.name 属性,该描述符在赋值为window.name = 1 时有一个setter to convert it to string:

有效的浏览上下文名称是包含至少一个不以 U+005F LOW LINE 字符开头的字符的任何字符串。 (以下划线开头的名称是为特殊关键字保留的。)

当在全局范围内执行时,var name = ...window.name 赋值。而letconst 声明块范围的变量。

当在本地范围内执行时,name 在这两种情况下都会引用本地变量:

(() => 
 var obj = name: 1;
 var name = obj; 
 console.log(typeof name); // 'number'
)();

【讨论】:

解决办法是使用块作用域和"use strict"来避免意外结果? @guest271314 是的。功能范围就足够了。这就是我们过去在任何地方都使用所有这些 IIFE 的原因——以免与全局范围发生冲突。为了清楚起见,我从 sn-p 中删除了“use strict”。默认情况下是可取的,但不会影响结果,因此这里不相关。 var 的这种行为是否是开发和实施letconst 的原因之一?既然var 现在可以在浏览器环境中使用,还有一个避免使用var 的理由吗? @guest271314 是的。如今,如果需要全球化,我们会做window.foo = ...。使用var foo = ... 意外分配给全局是不可取的。实际上,使用var foo = ... 故意分配给全局也是不可取的,因为它在严格模式下不起作用。 我不会将全局 let/const 声明称为“块作用域”。

以上是关于使用对象解构赋值时,为啥将属性“名称”转换为字符串? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

当组件中有解构赋值时,为啥默认道具不能防止 TypeError?

JavaScript 常用技巧

ES6中字符串的解构赋值

复习es6-解构赋值+字符串的扩展

ES6对象的新功能与解构赋值

解构赋值语法