Modules
Module Division
A program can be divided into multiple compilation units or modules.
Each module has its own scope. Any declaration (variables, functions, classes, etc.) created within a module is not visible outside of that module unless it is explicitly exported.
Conversely, variables, functions, classes, interfaces, etc., exported from another module must first be imported into the module.
Exporting
Top - level declarations can be exported using the export keyword.
Declarations that are not exported are considered private and can only be used within the module where they are declared.
export class Point {
x: number = 0;
y: number = 0;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
export let Origin = new Point(0, 0);
export function Distance(p1: Point, p2: Point): number {
return Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
}
Importing
Static Imports
Import declarations are used to import entities exported from other modules and provide their bindings within the current module. An import declaration consists of two parts:
- The import path, which specifies the module to import.
- The import binding, which defines the set of available entities from the imported module and their form of use (qualified or unqualified).
Import bindings can take several forms. Suppose a module has the path "./utils" and exports entities "X" and "Y".
The import binding * as A means that the binding name "A" is used, and all entities exported from the module specified by the import path can be accessed via A.name:
import * as Utils from './utils';
Utils.X // Refers to X from Utils
Utils.Y // Refers to Y from Utils
The import binding { ident1, ..., identN } means that the exported entities are bound to the specified names, which can be used as simple names:
import { X, Y } from './utils';
X // Refers to X from utils
Y // Refers to Y from utils
If the identifier list defines ident as alias, the entity ident is bound under the name alias:
import { X as Z, Y } from './utils';
Z // Refers to X from Utils
Y // Refers to Y from Utils
X // Compile-time error: 'X' is not visible
Dynamic Imports
In some scenarios of application development, if you want to import modules conditionally or on - demand, you can use dynamic imports instead of static imports.
The import() syntax is commonly referred to as dynamic import. It is a function - like expression used to dynamically import modules. When called in this way, it returns a promise.
As shown in the following example, import(modulePath) can load a module and return a promise that resolves to a module object containing all its exports. This expression can be called anywhere in the code.
// Calc.ts
export function add(a: number, b: number): number {
let c = a + b;
console.info('Dynamic import, %d + %d = %d', a, b, c);
return c;
}
// Index.ts
import("./Calc").then((obj: ESObject) => {
console.info(obj.add(3, 5));
}).catch((err: Error) => {
console.error("Module dynamic import error: ", err);
});
If used within an async function, you can use let module = await import(modulePath):
// say.ts
export function hi() {
console.log('Hello');
}
export function bye() {
console.log('Bye');
}
Dynamic imports can be performed as follows:
async function test() {
let ns = await import('./say');
let hi = ns.hi;
let bye = ns.bye;
hi();
bye();
}
For more business scenarios and examples of using dynamic import, see Dynamic Import.
Importing Open Capabilities of HarmonyOS SDK
The open capabilities (interfaces) provided by the HarmonyOS SDK also need to be used after an import declaration. You can directly import the interface module to use all the interface capabilities within that module. For example:
import UIAbility from '@ohos.app.ability.UIAbility';
Starting from HarmonyOS NEXT Developer Preview 1, the concept of Kit was introduced. The SDK encapsulates interface modules under the same Kit. Developers can use the interfaces included in a Kit by importing the Kit in the sample code. The interface modules encapsulated in a Kit can be viewed in the definitions of each Kit under the Kit subdirectory in the SDK directory.
There are three ways to use open capabilities by importing a Kit:
Method 1: Import the interface capabilities of a single module under a Kit. For example:
import { UIAbility } from '@kit.AbilityKit';
Method 2: Import the interface capabilities of multiple modules under a Kit. For example:
import { UIAbility, Ability, Context } from '@kit.AbilityKit';
Method 3: Import all interface capabilities included in a Kit. For example:
import * as module from '@kit.AbilityKit';
Here, "module" is an alias that can be customized. The interfaces of the module can then be called using this name.
Note: Method 3 may import too many unnecessary modules, leading to a large compiled HAP package and excessive resource consumption. Use it with caution.
Top - level Statements
Top - level statements are statements written directly at the outermost level of a module. These statements are not wrapped in any function, class, or block - level scope. Top - level statements include variable declarations, function declarations, expressions, etc.
Top comments (0)