typescript handbook 学习笔记2

时间:2021-04-15 16:02:44

概述

这是我学习typescript的笔记。写这个笔记的原因主要有2个,一个是熟悉相关的写法;另一个是理清其中一些晦涩的东西。供以后开发时参考,相信对其他人也有用。

学习typescript建议直接看中文文档英文文档。我是看的英文文档

typescript handbook 学习笔记1

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!