created at 2023/08/05 04:27:03
updated at 2023/08/05 04:57:39
typescript
console.log(greet('john'));
//john
function greet(name: string): string {
if (name) {
return `hi${name}!`;
}
}
typescript
console.log(greet('john'));
//greet is not a function
//函数执行完成之后greet才被赋值
var greet = function (name: string): string {
if (name) {
return `hi${name}!`;
}
};
这两个代码段非常相似,但是他们的行为不一样,解析器会在代码解析阶段执行函数声明。而函数表达式只有在被赋值的时候才会执行。区别在于一个“变量提升”的过程。
typescript
//这个函数的类型可以从被赋值的函数推断出来,因此,添加一个冗余的类型声明是没有必要的。
var greet:(name:string):string => string;
function(name:string):string{
if(name){
return `hi${name}!`
}
}
typescript
function add(val1:number,val2:number,val3?:number):number{
var result = val1+val2
if(val3!==undefined){
result+=val3
}
return result
}
typescript
function add(val1:number,val2:number,val3:number=0):number{
return val1+val2+val3;
}
void 0 是 typescript 编译器监测一个变量是否为 undefined 的用法。和可选参数一样,默认参数必须位于所有必选参数列表的后面。
typescript
function add(...val: number[]): number {
var result = [];
for (var i = 0; i < val.length; i++) {
result += val[i];
}
return result;
}
javascript
的 arguments 内建对象包含了被调用函数的所有参数。
typescript
function test(name:string):string;
function test(age:number):string;
function test(single:boolean):string;
function test(value:string|number|boolean):string{
switch(typeof value){
case "":
return ...
}
}
typescript
interface Document {
createElement(tagName: 'div'): HTMLDivElement; //特定重载签名
createElement(tagName: 'span'): HTMLSpanElement; //特定重载签名
createElement(tagName: 'canvas'): HTMLCanvasElement; //特定重载签名
createElement(tagName: 'string'): HTMLElement; //非特定重载签名
}
当在一个对象中声明特定签名时,这个对象中必须被赋予至少一个非特定重载签名。另外非重载签名必须放在最后。
typescript
function foo(): void {
if (true) {
var bar: number = 0;
}
alert(bar);
}
当调用这个函数的时候,alert 函数会显示变量的值,因为所有函数中的变量都在整个函数体的作用域内,所有的变量声明都会在函数执行前移动到函数的顶端,即变量提升。
typescript
function foo:void(){
var bar:number
if(true){
bar = 0
}
alert(bar)
}
同样
typescript
function foo(): void {
bar = 0;
var bar: number;
alert(bar);
}
//转换为:
function foo(): void {
var bar: number;
bar = 0;
alert(bar);
}
为解决这一问题引入了 let,const.let 关键字允许我们将作用域设置在代码段(if,while,for 等)而不只是在函数中。
typescript
function foo(): void {
if (true) {
let bar: number = 0;
bar = 1; //bar只在if代码块中被访问
}
alert(bar); //error
}
当使用 const 进行定义时,它和 let 拥有同样的作用域规则,并且不能被重新赋值。
typescript
var bar = 0;
(function () {
var foo: number = 0;
bar = 1;
console.log(bar); //1
console.log(foo); //0
})();
console.log(bar); //1
console.log(foo); //error
我们也可以给IIFE
传递一个参数,以便更好地精致作用域之外创建的变量。
typescript
var bar = 0(function (global) {
var foo: number = 0;
bar = 1;
console.log(global.bar); //1
console.log(foo); //0
})(this);
console.log(bar); //1
console.log(foo); //error
IIFE
允许我们访问公开的方法,隐藏函数内的私有变量。
typescript
class Counter {
private _i: number;
constructor() {
this._i = 0;
}
get(): number {
return this._i;
}
set(val: number): void {
this._i = val;
}
increment(): void {
this._i++;
}
}
var counter = new Counter();
console.log(counter.get()); //0
conunter.set(2);
console.log(counter.get()); //2
counter.increment();
console.log(counter.get()); //3
console.log(counter._i); //error:_i为私有属性
编译为 JavaScript
javascript
var Counter = (function () {
function Counter() {
this._i = 0;
}
Counter.prototype.get = function () {
return this._i;
};
Counter.prototype.set = function (val) {
this._i = val;
};
Counter.prototype.increment = function () {
this._i++;
};
return Counter;
})();
var counter = new Counter();
console.log(counter.get()); //0
counter.set(2);
console.log(counter.get()); //2
counter.increment();
console.log(counter.get()); //3
// console.log(counter._i);
这段代码在大部分场景都可运行,但如果在浏览器内执行这段代码,创建一个 Counter 实例并访问_i 也不会报错。因为
ts
不会生成运行时的私有属性。有时候需要我们编写在运行时拥有私有变量的函数就可以使用 IIFE。
typescript
var Counter = (function () {
//编译为js后,_i 并不是Counter类的属性,而是一个在Counter闭包内的变量
var _i: number = 0;
function Counter() {}
Counter.prototype.get = function () {
return _i;
};
Counter.prototype.set = function (val: number): void {
_i = val;
};
Counter.prototype.increament = function () {
_i++;
};
return Counter;
})();
闭包的职责是引用自由变量。换句话说,函数定义的位置所在的闭包会记住它所在的环境。
typescript
class User {
constructor() {}
getUsers(callback: (user: User[]) => void): void {}
}
class Order {
constructor() {}
getOrders(callback: (user: Order[]) => void): void {}
}
getUsers 和 getOrders 函数几乎完全相同,对此我们可以使用泛型来解决类型重复。
typescript
function getEntities<T>(url: string, callback: (list: T[]) => void): void {}