Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Common
/
code_guideline
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 1ebb2618
authored
Apr 24, 2020
by
zhao shuan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
init
0 parents
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
808 additions
and
0 deletions
async.md
code_guideline.md
typescript_advance.md
async.md
0 → 100644
View file @
1ebb261
-
在JavaScript的世界中,所有代码都 是单线程执行的
-
由于这个“缺陷”,导致 JavaScript 的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现
-
异步操作会在将来的某个时间点触发一个函数调用
-
主流的异步处理方案主要有:回调函数 (CallBack) 、 Promise 、 Generator 函数、 async/await。
# 回调函数
这是异步编程最基本、最直观的方式
```
javascript
downloadAsync
(
"http://example.com/file.txt"
,
(
text
)
=>
{
console
.
log
(
text
);
});
```
# Promise
解决回调嵌套层数过多的问题
```
javascript
downloadAsync
(
"a.txt"
,
(
a
)
=>
{
downloadAsync
(
"b.txt"
,
(
b
)
=>
{
downloadAsync
(
"c.txt"
,
(
c
)
=>
{
console
.
log
(
"Contents: "
+
a
+
b
+
c
);
},
function
(
error
)
{
console
.
log
(
"Error: "
+
error
);
});
},
function
(
error
)
{
console
.
log
(
"Error: "
+
error
);
});
},
function
(
error
)
{
console
.
log
(
"Error: "
+
error
);
});
```
```
javascript
downloadAsync
(
"a.txt"
).
then
(()
=>
{
return
downloadAsync
(
"b.txt"
);
}).
then
((
b
)
=>
{
return
downloadAsync
(
"c.txt"
);
}).
then
((
c
)
=>
{
console
.
log
(
"Contents: "
+
a
+
b
+
c
);
}).
catch
((
error
)
=>
{
console
.
log
(
"Error: "
+
error
);
});
```
```
javascript
var
myPromise
=
new
Promise
((
resolve
,
reject
)
=>
{
...
//异步操作
if
(
success
)
{
resolve
(
value
);
}
else
{
reject
(
error
);
}
});
```
```
javascript
var
myPromise
=
new
Promise
((
resolve
,
reject
)
=>
{
resolve
(
1
);
});
myPromise
.
then
((
value
)
=>
{
console
.
log
(
"第"
+
value
+
"一次异步操作成功"
);
//第1次异步操作成功
return
value
+
1
;
}).
then
(
function
(
value
)
{
console
.
log
(
"第"
+
value
+
"一次异步操作成功"
);
//第2次异步操作成功
});
```
# Generator
Promise异步编程,可以很好地回避回调地狱。但Promise的问题是,不管什么样的异步操作,被Promise一包装,看上去都是一堆then,语义方面还不够清晰。因此更好的异步编程解决方案是ES6的Generator。
```
javascript
function
*
gen
()
{
yield
1
;
yield
2
;
yield
3
;
}
var
g
=
gen
();
console
.
log
(
g
);
// Generator {}
console
.
log
(
g
.
next
());
// { value: 1, done: false }
console
.
log
(
g
.
next
());
// { value: 2, done: false }
console
.
log
(
g
.
next
());
// { value: 3, done: true }
console
.
log
(
g
.
next
());
// { value: undefined, done: true }
```
调用Generator只会得到一个遍历器对象,仅此而已。并不会执行Generator函数。上例中var g = gen();,变量g是一个遍历器对象,即一个指向内部状态的指针对象,用于之后遍历yield定义的内部状态。
有了遍历器对象g之后,就可以使用next方法使指针依次移向下一个状态,即让函数从开头或上一次暂停的地方开始执行,执行到下一个yield或return语句为止。虽然yeild和next本质上是遍历器对象和操作指针,但你使用时可以将它们简单地理解为:
>Generator是分段执行的函数。yeild是暂停的标记。next用于继续执行。
## 自动遍历
```
javascript
function
*
numbers
()
{
yield
1
;
yield
2
;
return
3
;
yield
4
;
}
//for...of
var
gen1
=
numbers
();
for
(
let
n
of
gen1
)
{
console
.
log
(
n
);
//1 2
}
//Array.from
console
.
log
(
Array
.
from
(
numbers
()));
// [1, 2]
//扩展运算符(…)
console
.
log
([...
numbers
()]);
// [1, 2]
//解构赋值
let
[
x
,
y
]
=
numbers
();
console
.
log
(
x
);
//1
console
.
log
(
y
);
//2
```
## 应用
```
javascript
function
delay
(
time
,
callback
){
setTimeout
(
function
(){
callback
(
"sleep "
+
time
);
},
time
);
}
delay
(
1000
,
function
(
msg
){
console
.
log
(
msg
);
delay
(
2000
,
function
(
msg
){
console
.
log
(
msg
);
});
});
//1秒后打印出:sleep 1000
//再过2秒打印出:sleep 2000
```
```
javascript
function
delay
(
time
,
callback
){
setTimeout
(
function
(){
callback
(
"sleep "
+
time
);
},
time
);
}
function
run
(
genFunc
)
{
var
g
=
genFunc
(
resume
);
function
resume
(
value
)
{
g
.
next
(
value
);
}
g
.
next
();
}
run
(
function
*
delayedMsg
(
resume
)
{
console
.
log
(
yield
delay
(
1000
,
resume
));
console
.
log
(
yield
delay
(
2000
,
resume
));
});
//1秒后打印出:sleep 1000
//再过2秒打印出:sleep 2000
```
# async/await
async函数就是Generator函数的语法糖,使得异步操作的流程更加清晰。
```
javascript
function
delay
(
time
){
return
new
Promise
(
function
(
resolve
)
{
setTimeout
(
function
(){
resolve
(
"sleep "
+
time
);
},
time
);
});
}
async
function
run
()
{
console
.
log
(
await
delay
(
1000
));
console
.
log
(
await
delay
(
2000
));
}
```
async函数的await命令后面是Promise对象(如果是原始类型的值,会自动将其转成Promise对象并立即将状态设成Resolved,效果等于同步操作)。进一步说,async函数完全可以看作多个异步操作,包装成的一个Promise对象,而await命令就是内部then命令的语法糖。因为await命令后面是Promise对象,需要考虑rejected的情况,毕竟谁也不能断言异步操作中不会出现异常,所以最好把await命令包进try…catch中:
```
javascript
async
function
myAsyncFun
()
{
try
{
await
somePromise
();
}
catch
(
err
)
{
console
.
log
(
err
);
}
}
//另一种写法
async
function
myAsyncFun
()
{
await
somePromise
().
catch
(
function
(
err
)
{
console
.
log
(
err
);});
}
```
code_guideline.md
0 → 100644
View file @
1ebb261
# 代码规范 - 命名
## 变量名和函数
使用驼峰(camelCase)命名变量和函数名
```
typescript
let
fooVar
:
string
;
function
barFunc
():
void
{
}
```
## 类
使用帕斯卡(PascalCase)命名类名
```
typescript
class
Foo
{
}
```
使用驼峰(camelCase)命名类成员变量和方法
```
typescript
class
Foo
{
bar
:
number
;
baz
()
{
}
}
```
## 接口
与类相似
```
typescript
interface
Foo
{
foo
:
number
;
baz
():
void
;
}
```
## 类型
与接口类似
```
typescript
type
T
=
Foo
|
Bar
;
```
## 命名空间
使用帕斯卡(PascalCase)命名
## 枚举
使用帕斯卡(PascalCase)命名枚举类型和成员
```
typescript
enum
Color
{
Red
,
Blue
}
```
## 数组
声明数组时使用
```let foos:Foo[];```
而不是
```let foos:Array<Foo>;```
,便于阅读。
## 常量
模块级常,采用大写字母加下划线方式,如:
```
typescript
export
const
UNITY_RES_BASE
=
"res/unity/LayaScene_prefabs/Conventional"
;
export
const
BASE_PLAYER_SCALE
=
0.4
;
export
const
BASE_WEAPON_SCALE
=
0.6
;
```
函数内部自用常量,同变量使用驼峰(camelCase)命名。(目的:防止自己不小心改变指向造成bug)
# 代码风格及注意事项
## 类型
能声明出类型的都要使用明确的类型,除非极特殊情况用
`any`
。
工具中特殊的函数,如
`function shallowCompare(obj1: any, obj2: any)`
,否则能用函数优先考虑泛型。
## 修饰符
变量使用
`let`
声明,不使用
`var`
;
不允许改变指向的变量用
`const`
;只读类型用
`Readonly`
/
`DeepReadonly`
。
对于系统预定义常量对象使用
`const`
与
`Readonly`
结合,如:
```
typescript
export
const
FLICK_ARR
:
Readonly
<
string
[]
>
=
[
"break"
,
"freeze"
];
```
## 风格
1.
使用箭头函数代替匿名函数表达式。
2.
只在需要的时候才把箭头函数的参数括起来。比如
```
typescript
x
=>
x
+
x
(
x
,
y
)
=>
x
+
y
<
T
>
(
x
:
T
,
y
:
T
)
=>
x
===
y
```
3.
总是使用
`{}`
把循环体和条件语句括起来。
4.
每个变量声明语句只声明一个变量。不要
`let x = 1, y = 2;`
,而是
`let x = 1; let y = 2;`
。
5.
回调函数总是把参数和返回值函数声明出来,不要使用
`Function`
。
6.
代码使用vs code工具格式化。
7.
一行过长的时候,要拆成多行。
8.
一个函数过长,考虑将其中某些代码块抽成函数。
9.
类的成员变量和函数优先考虑private,其次protected,谨慎public。
## 函数里的this
尽量不使用
`bind`
函数,因ts无法识别里面的
`this`
。使用箭头函数绑定this。
### this和箭头函数
JavaScript里,this的值在函数被调用的时候才会指定。 这是个既强大又灵活的特点,但是你需要花点时间弄清楚函数调用的上下文是什么。 但众所周知,这不是一件很简单的事,尤其是在返回一个函数或将函数当做参数传递的时候。
```
typescript
let
deck
=
{
suits
:
[
"hearts"
,
"spades"
,
"clubs"
,
"diamonds"
],
cards
:
Array
(
52
),
createCardPicker
:
function
()
{
return
function
()
{
let
pickedCard
=
Math
.
floor
(
Math
.
random
()
*
52
);
let
pickedSuit
=
Math
.
floor
(
pickedCard
/
13
);
return
{
suit
:
this
.
suits
[
pickedSuit
],
card
:
pickedCard
%
13
};
}
}
}
let
cardPicker
=
deck
.
createCardPicker
();
let
pickedCard
=
cardPicker
();
console
.
log
(
"card: "
+
pickedCard
.
card
+
" of "
+
pickedCard
.
suit
);
```
为了解决这个问题,我们可以在函数被返回时就绑好正确的this。 这样的话,无论之后怎么使用它,都会引用绑定的‘deck’对象。 我们需要改变函数表达式来使用ECMAScript 6箭头语法。 箭头函数能保存函数创建时的this值,而不是调用时的值:
```
typescript
let
deck
=
{
suits
:
[
"hearts"
,
"spades"
,
"clubs"
,
"diamonds"
],
cards
:
Array
(
52
),
createCardPicker
:
function
()
{
// NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
return
()
=>
{
let
pickedCard
=
Math
.
floor
(
Math
.
random
()
*
52
);
let
pickedSuit
=
Math
.
floor
(
pickedCard
/
13
);
return
{
suit
:
this
.
suits
[
pickedSuit
],
card
:
pickedCard
%
13
};
}
}
}
let
cardPicker
=
deck
.
createCardPicker
();
let
pickedCard
=
cardPicker
();
console
.
log
(
"card: "
+
pickedCard
.
card
+
" of "
+
pickedCard
.
suit
);
```
不幸的是,
`this.suits[pickedSuit]`
的类型依旧为
`any`
。 这是因为
`this`
来自对象字面量里的函数表达式。 修改的方法是,提供一个显式的
`this`
参数。
`this`
参数是个假的参数,它出现在参数列表的最前面
```
typescript
interface
Card
{
suit
:
string
;
card
:
number
;
}
interface
Deck
{
suits
:
string
[];
cards
:
number
[];
createCardPicker
(
this
:
Deck
):
()
=>
Card
;
}
let
deck
:
Deck
=
{
suits
:
[
"hearts"
,
"spades"
,
"clubs"
,
"diamonds"
],
cards
:
Array
(
52
),
// NOTE: The function now explicitly specifies that its callee must be of type Deck
createCardPicker
:
function
(
this
:
Deck
)
{
return
()
=>
{
let
pickedCard
=
Math
.
floor
(
Math
.
random
()
*
52
);
let
pickedSuit
=
Math
.
floor
(
pickedCard
/
13
);
return
{
suit
:
this
.
suits
[
pickedSuit
],
card
:
pickedCard
%
13
};
}
}
}
let
cardPicker
=
deck
.
createCardPicker
();
let
pickedCard
=
cardPicker
();
console
.
log
(
"card: "
+
pickedCard
.
card
+
" of "
+
pickedCard
.
suit
);
```
### 回调函数里的this
当你将一个函数传递到某个库函数里在稍后被调用时,你可能也见到过回调函数里的this会报错。 因为当回调函数被调用时,它会被当成一个普通函数调用,this将为undefined。 稍做改动,你就可以通过this参数来避免错误。
```
typescript
interface
UIElement
{
addClickListener
(
onclick
:
(
this
:
void
,
e
:
Event
)
=>
void
):
void
;
}
```
```
typescript
class
Handler
{
info
:
string
;
onClickBad
(
this
:
Handler
,
e
:
Event
)
{
// oops, used this here. using this callback would crash at runtime
this
.
info
=
e
.
message
;
}
}
let
h
=
new
Handler
();
uiElement
.
addClickListener
(
h
.
onClickBad
);
// error!
```
```
typescript
class
Handler
{
info
:
string
;
onClickGood
(
this
:
void
,
e
:
Event
)
{
// can't use this here because it's of type void!
console
.
log
(
'clicked!'
);
}
}
let
h
=
new
Handler
();
uiElement
.
addClickListener
(
h
.
onClickGood
);
```
```
typescript
class
Handler
{
info
:
string
;
onClickGood
=
(
e
:
Event
)
=>
{
this
.
info
=
e
.
message
}
}
```
## 事件机制
```
typescript
function
onMouseDown
()
{
}
element
.
on
(
"mousedown"
,
onMouseDown
);
element
.
off
(
"mousedown"
,
onMouseDown
);
element
.
emit
(
"mousedown"
,
mouseEvent
);
```
```
typescript
const
emitter
=
new
Emitter
();
export
namespace
CameraEvents
{
export
const
CHENG_STATE
=
emitter
.
createEvent
<
(
state
:
ECameraState
)
=>
void
>
();
export
const
SET_OFFSET
=
emitter
.
createEvent
<
(
factor
:
number
,
rotateX
:
number
,
position
:
Laya
.
Vector3
)
=>
void
>
();
export
const
SET_FACTOR
=
emitter
.
createEvent
<
(
factor
:
number
)
=>
void
>
();
}
class
XXX
{
private
disposable
=
new
CompositeDisposable
;
regiterEvents
()
{
this
.
disposable
.
add
(
CameraEvents
.
CHENG_STATE
.
on
(()
=>
{}));
this
.
disposable
.
add
(
CameraEvents
.
SET_OFFSET
.
on
(()
=>
{}));
}
unregisterEvents
()
{
this
.
disposable
.
dispose
();
}
setCameraFactor
()
{
CameraEvents
.
SET_FACTOR
.
emit
(
2
);
}
}
```
## 模块循环依赖
如果只是作为类型引用,严格来说不算依赖。
设计上应单向依赖,避免循环依赖。
-
使用事件机制解耦
-
耦合太深的写到一个模块
-
类型/模型单独放到模块中,不依赖任何其它模块
typescript_advance.md
0 → 100644
View file @
1ebb261
# Map & Set
## 使用索引类型
```
typescript
let
userInfo
:
{[
index
:
string
]:
string
}
=
{};
userInfo
[
"name"
]
=
"typescript"
;
userInfo
[
"age"
]
=
"14"
;
```
## Map类型
```
typescript
let
nameScore
=
new
Map
<
string
,
number
>
([[
"Michael"
,
95
],
[
"Bob"
,
75
],
[
"Tracy"
,
85
]]);
nameScore
.
get
(
"Michael"
);
// 95
nameScore
.
has
(
"Bob"
);
// 判断是否存在
nameScore
.
set
(
"Adam"
,
70
);
// 添加新的
nameScore
.
set
(
"Bob"
,
63
);
// 修改
nameScore
.
delete
(
"Tracy"
);
// 删除
// 遍历
for
(
let
item
of
nameScore
)
{
console
.
log
(
`name:
${
item
[
0
]}
, score:
${
item
[
1
]}
`
);
}
```
## Set类型
```
typescript
let
s
=
new
Set
<
number
>
([
1
,
2
,
3
]);
s
.
add
(
4
);
// 1, 2, 3, 4
s
.
add
(
2
);
// 1, 2, 3, 4
s
.
delete
(
3
);
// 1, 2, 4
```
# 泛型
```
typescript
function
echo
(
arg
:
any
):
any
{
return
arg
;
}
```
```
typescript
function
echo
<
T
>
(
arg
:
T
):
T
{
return
arg
;
}
let
output1
=
identity
<
string
>
(
"myString"
);
let
output2
=
identity
(
"myString"
);
// type of output will be 'string'
```
## 泛型类
```
typescript
class
GenericNumber
<
T
>
{
zeroValue
:
T
;
add
:
(
x
:
T
,
y
:
T
)
=>
T
;
}
let
myGenericNumber
=
new
GenericNumber
<
number
>
();
myGenericNumber
.
zeroValue
=
0
;
myGenericNumber
.
add
=
function
(
x
,
y
)
{
return
x
+
y
;
};
```
## 泛型约束
```
typescript
interface
Lengthwise
{
length
:
number
;
}
function
loggingIdentity
<
T
extends
Lengthwise
>
(
arg
:
T
):
T
{
console
.
log
(
arg
.
length
);
// Now we know it has a .length property, so no more error
return
arg
;
}
```
## 在泛型约束中使用类型参数
```
typescript
function
getProperty
<
T
,
K
extends
keyof
T
>
(
obj
:
T
,
key
:
K
)
{
return
obj
[
key
];
}
let
x
=
{
a
:
1
,
b
:
2
,
c
:
3
,
d
:
4
};
getProperty
(
x
,
"a"
);
// okay
getProperty
(
x
,
"m"
);
// error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
```
## 在泛型里使用类类型
```
typescript
class
BeeKeeper
{
hasMask
:
boolean
;
}
class
ZooKeeper
{
nametag
:
string
;
}
class
Animal
{
numLegs
:
number
;
}
class
Bee
extends
Animal
{
keeper
:
BeeKeeper
;
}
class
Lion
extends
Animal
{
keeper
:
ZooKeeper
;
}
function
createInstance
<
A
extends
Animal
>
(
c
:
new
()
=>
A
):
A
{
return
new
c
();
}
createInstance
(
Lion
).
keeper
.
nametag
;
// typechecks!
createInstance
(
Bee
).
keeper
.
hasMask
;
// typechecks!
```
# 高级类型
## 交叉类型
交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。 例如,
`Person & Serializable & Loggable`
同时是
`Person`
和
`Serializable`
和
`Loggable`
。 就是说这个类型的对象同时拥有了这三种类型的成员。
## 联合类型
联合类型与交叉类型很有关联,但是使用上却完全不同。 偶尔你会遇到这种情况,一个代码库希望传入
`number`
或
`string`
类型的参数。 例如下面的函数:
```
typescript
/**
* Takes a string and adds "padding" to the left.
* If 'padding' is a string, then 'padding' is appended to the left side.
* If 'padding' is a number, then that number of spaces is added to the left side.
*/
function
padLeft
(
value
:
string
,
padding
:
string
|
number
)
{
if
(
typeof
padding
===
"number"
)
{
return
Array
(
padding
+
1
).
join
(
" "
)
+
value
;
}
if
(
typeof
padding
===
"string"
)
{
return
padding
+
value
;
}
throw
new
Error
(
`Expected string or number, got '
${
padding
}
'.`
);
}
padLeft
(
"Hello world"
,
4
);
// returns " Hello world"
```
如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员。
```
typescript
interface
Bird
{
fly
();
layEggs
();
}
interface
Fish
{
swim
();
layEggs
();
}
function
getSmallPet
():
Fish
|
Bird
{
// ...
}
let
pet
=
getSmallPet
();
pet
.
layEggs
();
// okay
pet
.
swim
();
// errors
if
((
<
Fish
>
pet
).
swim
)
{
(
<
Fish
>
pet
).
swim
();
// okay
}
```
## 类型保护
```
typescript
function
isFish
(
pet
:
Fish
|
Bird
):
pet
is
Fish
{
return
(
<
Fish
>
pet
).
swim
!==
undefined
;
}
if
(
isFish
(
pet
))
{
pet
.
swim
();
}
else
{
pet
.
fly
();
}
```
### typeof类型保护
`typeof`
类型保护只有两种形式能被识别:
`typeof v === "typename"`
和
`typeof v !== "typename"`
,
`"typename"`
必须是
`"number"`
,
`"string"`
,
`"boolean"`
或
`"symbol"`
。 但是TypeScript并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型保护。
```
typescript
function
padLeft
(
value
:
string
,
padding
:
string
|
number
)
{
if
(
typeof
padding
===
"number"
)
{
return
Array
(
padding
+
1
).
join
(
" "
)
+
value
;
}
if
(
typeof
padding
===
"string"
)
{
return
padding
+
value
;
}
throw
new
Error
(
`Expected string or number, got '
${
padding
}
'.`
);
}
```
### instanceof类型保护
```
typescript
interface
Padder
{
getPaddingString
():
string
}
class
SpaceRepeatingPadder
implements
Padder
{
constructor
(
private
numSpaces
:
number
)
{
}
getPaddingString
()
{
return
Array
(
this
.
numSpaces
+
1
).
join
(
" "
);
}
}
class
StringPadder
implements
Padder
{
constructor
(
private
value
:
string
)
{
}
getPaddingString
()
{
return
this
.
value
;
}
}
function
getRandomPadder
()
{
return
Math
.
random
()
<
0.5
?
new
SpaceRepeatingPadder
(
4
)
:
new
StringPadder
(
" "
);
}
// 类型为SpaceRepeatingPadder | StringPadder
let
padder
:
Padder
=
getRandomPadder
();
if
(
padder
instanceof
SpaceRepeatingPadder
)
{
padder
;
// 类型细化为'SpaceRepeatingPadder'
}
if
(
padder
instanceof
StringPadder
)
{
padder
;
// 类型细化为'StringPadder'
}
```
## 类型别名
```
typescript
type
Name
=
string
;
type
NameResolver
=
()
=>
string
;
type
NameOrResolver
=
Name
|
NameResolver
;
function
getName
(
n
:
NameOrResolver
):
Name
{
if
(
typeof
n
===
'string'
)
{
return
n
;
}
else
{
return
n
();
}
}
```
```
typescript
type
Alias
=
{
num
:
number
}
interface
Interface
{
num
:
number
;
}
declare
function
aliased
(
arg
:
Alias
):
Alias
;
declare
function
interfaced
(
arg
:
Interface
):
Interface
;
```
类型别名不能被
`extends`
和
`implements`
(自己也不能
`extends`
和
`implements`
其它类型)。我们应该尽量去使用接口代替类型别名。如果你无法通过接口来描述一个类型并且需要使用联合类型或元组类型,这时通常会使用类型别名。
# 模块
从ECMAScript 2015开始,JavaScript引入了模块的概念。TypeScript也沿用这个概念。
模块在其自身的作用域里执行,而不是在全局作用域里;这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非你明确地使用export形式之一导出它们。 相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用import形式之一。
模块是自声明的;两个模块之间的关系是通过在文件级别上使用imports和exports建立的。
## 导出
任何声明(比如变量,函数,类,类型别名或接口)都能够通过添加export关键字来导出。
ZipCodeValidator.ts
```
typescript
export
interface
StringValidator
{
isAcceptable
(
s
:
string
):
boolean
;
}
export
const
numberRegexp
=
/^
[
0-9
]
+$/
;
export
class
ZipCodeValidator
implements
StringValidator
{
isAcceptable
(
s
:
string
)
{
return
s
.
length
===
5
&&
numberRegexp
.
test
(
s
);
}
}
```
重新导出
ParseIntBasedZipCodeValidator.ts
```
typescript
export
class
ParseIntBasedZipCodeValidator
{
isAcceptable
(
s
:
string
)
{
return
s
.
length
===
5
&&
parseInt
(
s
).
toString
()
===
s
;
}
}
// 导出原先的验证器但做了重命名
export
{
ZipCodeValidator
as
RegExpBasedZipCodeValidator
}
from
"./ZipCodeValidator"
;
```
AllValidators.ts
```
typescript
export
*
from
"./StringValidator"
;
// exports interface StringValidator
export
*
from
"./LettersOnlyValidator"
;
// exports class LettersOnlyValidator
export
*
from
"./ZipCodeValidator"
;
// exports class ZipCodeValidator
```
## 导入
```
typescript
import
{
ZipCodeValidator
}
from
"./ZipCodeValidator"
;
let
myValidator
=
new
ZipCodeValidator
();
```
导入重命名
```
typescript
import
{
ZipCodeValidator
as
ZCV
}
from
"./ZipCodeValidator"
;
let
myValidator
=
new
ZCV
();
```
将整个模块导入到一个变量
```
typescript
import
*
as
validator
from
"./ZipCodeValidator"
;
let
myValidator
=
new
validator
.
ZipCodeValidator
();
```
## 默认导出和导入
ZipCodeValidator.ts
```
typescript
export
default
class
ZipCodeValidator
{
static
numberRegexp
=
/^
[
0-9
]
+$/
;
isAcceptable
(
s
:
string
)
{
return
s
.
length
===
5
&&
ZipCodeValidator
.
numberRegexp
.
test
(
s
);
}
}
```
```
typescript
import
validator
from
"./ZipCodeValidator"
;
let
myValidator
=
new
validator
();
```
## JavaScript模块
-
Node.js(CommonJS)
-
Require.js(AMD)
-
isomorphic (UMD)
-
SystemJS
-
ECMAScript 2015 native modules
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment