typescript handbook 学习笔记2
概述
这是我学习typescript的笔记。写这个笔记的原因主要有2个,一个是熟悉相关的写法;另一个是理清其中一些晦涩的东西。供以后开发时参考,相信对其他人也有用。
学习typescript建议直接看中文文档或英文文档。我是看的英文文档。
var的坑
变量提升和函数作用域
变量提升和函数作用域不过多说明,上一段代码。
//块中声明的变量被提升了
function f1(shouldInitialize) {
if (shouldInitialize) {
var x = 10;
}
return x;
}
f1(true); // returns '10'
f1(false); // returns 'undefined'
function f2(shouldInitialize) {
return x;
}
f2(false); // error,Uncaught ReferenceError(未声明)
这就导致在块里面写错的话很难发现。比如下面这个例子。
function sumMatrix(matrix: number[][]) {
var sum = 0;
for (var i = 0; i < matrix.length; i++) {
var currentRow = matrix[i];
for (var i = 0; i < currentRow.length; i++) {
sum += currentRow[i];
}
}
return sum;
}
IIFE
IIFE = an Immediately Invoked Function Expression,立即执行函数,闭包的用途之一。
原理:由于var的变量声明只有函数作用域,所以每进入一个函数作用域,用var声明的变量都会重新被声明->初始化。然而,如果没有进入到一个函数作用域,var声明的变量就不会被重新声明->初始化。所以为了让i在进入setTimeout之前重新初始化,就需要用一个函数作用域把它包裹起来。(虽然setTimeout的参数里面有一个函数,但是这个函数是一个异步的,并不立刻执行。)
for (var i = 0; i < 10; i++) {
// capture the current state of 'i'
// by invoking a function with its current value
(function(i) {
setTimeout(function() { console.log(i); }, 100 * i);
})(i);
}
let和const
let和const具有块级作用域,它们都没有变量提升,let不能反复声明,const不能反复声明和修改。
因为let具有块级作用域,那就表示每进入一个块,变量都会重新声明和初始化。所以我们经常会看到下面的代码:
for (let i = 0; i < 10 ; i++) {
setTimeout(function() { console.log(i); }, 100 * i);
}
能用const尽量用const,否则能用let尽量用let,最后才考虑var。
destructuring解构
//数组解构
let input = [1, 2];
let [first, second] = input;
//交换位置
[first, second] = [second, first];
//函数参数解构
function f([first, second]: [number, number]): void {
console.log(first);
}
//剩余部分解构
let [first, ...rest] = [1, 2, 3, 4];
console.log(rest); //[2, 3, 4]
//特定位置解构
let [first] = [1, 2, 3, 4];
let [, second, , fouth] = [1, 2, 3, 4];
//对象解构
let o = {
a: 'foo',
b: 12,
c: 'bar'
};
let {a, b} = o;
//赋予别名
let {a: newName1, b: newName2} = o;
//默认值
let {a, b=1001} = o;
//带默认值的函数参数解构
type C = { a: string, b?: number }
function f({ a, b=1001 }: C): void {
// ...
}
spread展开
//数组展开
let first = [1, 2];
let second = [3, 4];
let bothPlus = [0, ...first, ...second, 5];
//对象展开
let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { ...defaults, food: "rich" };
//food会被覆盖
let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { food: "rich", ...defaults };
//对象展开并不会复制方法
class C {
p = 12;
m() {
}
}
let c = new C();
let clone = { ...c };
clone.p; // ok
clone.m(); // error!