【发布时间】:2019-02-21 01:18:18
【问题描述】:
在 TypeScript 中,就像在 ECMAScript 2015 中一样,任何包含顶级
import或export的文件都被视为一个模块。相反,没有任何顶级import或export声明的文件被视为其内容在全局范围内可用的脚本(因此也可用于模块)。
导入或导出“顶级”是什么意思?
【问题讨论】:
标签: typescript
在 TypeScript 中,就像在 ECMAScript 2015 中一样,任何包含顶级
import或export的文件都被视为一个模块。相反,没有任何顶级import或export声明的文件被视为其内容在全局范围内可用的脚本(因此也可用于模块)。
导入或导出“顶级”是什么意思?
【问题讨论】:
标签: typescript
顶级import 是位于文件最顶部的静态导入。然而,它被称为“顶级”并不是因为它位于文件的顶部,而是因为存在不是顶级的动态导入:
import foo from 'foo' // top level import, static one
import('foo').then(/* ... */) // not top level import, dynamic one
// no static top-level import can live here (after any code that is not a top-level import declaration)
function bar() {
import('foo').then(/* ... */) // not top level import, dynamic one
// no static top-level import can live here
// no export can live here too
}
// no static top-level import can live here
export const baz = 123 // exports are always top level, and static
// You still can add not top level imports here, in the very end
import('foo').then(/* ... */)
现在,为什么这在 Typescript 中很重要?
如果你放置两个没有顶级导入/导出的文件,它们有两个相同的标识符,你会得到一个错误:
// a.ts
let foo = 1 // Error: duplicate identifier
// b.ts
let foo = 1 // Error: duplicate identifier
发生这种情况是因为没有顶级导出/导入声明,并且 TS 认为这些文件是 scripts(与 modules 形成对比)。如果你在浏览器中加载两个具有相同标识符的脚本会发生什么?对,会出现“重复标识符”错误。因为这两个变量都存在于全局命名空间中。
因此,为避免这种情况,您可以这样做:
// a.ts
let foo = 1 // Ok
// b.ts
let foo = 1 // Ok
export {} // This is the magic. b.ts is now a module and hence, is not polluting the global namespace.
【讨论】:
is a static import that is located at the very top of the file 这不是真的。导入的行号与是否为顶级无关。
use strict 或 cmets,因此从技术上讲,它们可能不在最顶部
typescript 中的顶层是最外层的作用域。
每次打开一组{ 大括号¹时,您都会创建一个范围。
作用域将变量和函数的可见性限制在它们定义的作用域和子作用域内。
例如:
import { something } from "<module>"; <-- Global / Top-level scope
function divide(x, y) { <-- Start function scope
if(y == 0) { <-- Start of the if's scope
/*
* Here is a child scope of the function
* This means x and y are available here.
*/
var error = new Error("Cannot divide by 0); <-- "error" is only available here.
throw error;
} <-- End of the if's scope
/*
* The "error" variable is not available here
* since the scope it was defined in, was already closed.
*/
return x / y;
} <-- Ends the functions scope
var z = 0; <-- Global scope
这意味着:
import { x } from "<module>"
/* rest of code */
有效,但例如:
if (true) {
import { x } from "<module>";
}
不起作用,因为导入包含在 if 语句的范围内,因此不再处于顶级范围内。
但这并不意味着“顶级”位于文件的顶部。它只是表示最外面的范围。
function add(a, b) {
return a + b;
}
import { x } from "<module>";
这仍然有效,因为函数的范围以结束 } 大括号¹结束。意味着它再次处于顶层之后的所有内容。
关于import 的所有内容也适用于export 的
1:有时您可以省略{|} 大括号来创建新范围。您仍然会创建一个新范围,但会隐式执行此操作。
例如,考虑下面的两个 sn-ps - 它们是相同的。语言根据词法创建范围 - 范围不是由标记定义的
if(true)
return true;
else
return false;
同
if(true) {
return true;
} else {
return false;
}
【讨论】: