TypeScript学习笔记之变量声明

原文地址:https://banggan.github.io/2019/01/18/TypeScript学习笔记-之变量声明/

变量声明

因为TypeScript是JavaScript的超集,所以它本身就支持let和const。const是对let的一个增强,它能阻止对一个变量再次赋值,在TS中,主要就是var let const,就简单说一下用法吧:

var声明

var a =10;       //定义变量
function f() {  //函数内部定义变量
    var message = "Hello, world!";

    return message;
}
//函数嵌套调用
function f() {
    var a = 1;

    a = 2;
    var b = g();
    a = 3;

    return b;

    function g() { //g可以获取到f函数定义的a
        return a;
    }
}

f(); // returns 2

let声明

let的声明与var一样,重要的是,let和var的区别是实现块级作用域,而且不存在变量提升,且不能重复赋值

这里我们定义了2个变量a和b。 a的作用域是f函数体内,而b的作用域是if语句块里

//内部能访问到b,但是外部就不能访问; 
function f(input: boolean) {
    let a = 100;

    if (input) {
        // Still okay to reference 'a'
        let b = a + 1;
        return b;
    }

    // Error: 'b' doesn't exist here
    return b;
}
//暂时性死区的例子
a++; // illegal to use 'a' before it's declared;
let a;

重复定义

let x = 10;
let x = 20; // 错误,不能在1个作用域里多次声明`x`

并不是要求两个均是块级作用域的声明TypeScript才会给出一个错误的警告。同样会发生错误

function f(x) {
    let x = 100; // error: interferes with parameter declaration
}

function g() {
    let x = 100;
    var x = 100; // error: can't have both declarations of 'x'
}

并不是说块级作用域变量不能用函数作用域变量来声明。 而是块级作用域变量需要在明显不同的块里声明。

function f(condition, x) {
    if (condition) {
        let x = 100;
        return x;
    }

    return x;
}

f(false, 0); // returns 0
f(true, 0);  // returns 100

当let声明出现在循环体里时拥有完全不同的行为。 不仅是在循环里引入了一个新的变量环境,而是针对 每次迭代都会创建这样一个新作用域。 这就是我们在使用立即执行的函数表达式时做的事。

for (let i = 0; i < 10 ; i++) {
    setTimeout(function() {console.log(i); }, 100 * i);
} //输出0-9

const声明

const和let基本一致,只是const声明的变量被赋值后不能再改变(所以对于const来说,只声明不赋值,就会报错),作用域同let

const numLivesForCat = 9;
const kitty = {
    name: "Aurora",
    numLives: numLivesForCat,
}

// Error
kitty = {
    name: "Danielle",
    numLives: numLivesForCat
};

// all "okay"
kitty.name = "Rory";
kitty.name = "Kitty";
kitty.name = "Cat";
kitty.numLives--;

let vs. const

使用最小特权原则,所有变量除了你计划去修改的都应该使用const。 基本原则就是如果一个变量不需要对它写入,那么其它使用这些代码的人也不能够写入它们,并且要思考为什么会需要对这些变量重新赋值。 使用 const也可以让我们更容易的推测数据的流动。

解构

解构(destructuring assignment)是一种表达式,将数组或者对象中的数据赋给另一变量。

数组解构
let input = [1, 2,3];
let [f, s] = input;
console.log(f); // outputs 1
console.log(s); // outputs 2

交换变量值

[f,s] = [s,f];
console.log(f); // outputs 2
console.log(s); // outputs 1

使用…创建剩余变量

let nums= [1,2,3,4]
let [f, ...rest] = nums;
console.log(f);   // 输出: 1
console.log(rest);// 输出: [2,3,4]

忽略数组中某些元素

let [first] = [1, 2, 3, 4];
console.log(first); // 输出: 1
let [, second, , fourth] = [1, 2, 3, 4];
对象解构
let o = {
    a: "foo",
    b: 12,
    c: "bar"
}
let { a, b } = o;
console.log(a);   // 输出: foo
console.log(b);// 输出: 12

将对象o.a赋值给a,0.b赋值给b,这里的a,b都是对象属性名且必须一致,而属性c则会忽略

上述例子中声明的变量a和b必须和对象中属性一致,如果想换一个名字,写法如下:

let { a: aa, b: bb } = o;
默认值

let o = {
    a: "foo",
    b: undefined,
    c: "bar"
}
let {a, b=1}= o;
console.log(a);   // 输出: foo
console.log(b);// 输出: 1

当属性b的值为undefined时,解构表达式会使用默认值

展开

展开操作符正与解构相反。 它允许你将一个数组展开为另一个数组,或将一个对象展开为另一个对象。

数组展开

let first = [1, 2];
let second = [3, 4];
let bothPlus = [0, ...first, ...second, 5];
console.log(bpthPlus);输出 [0,1,2,3,4,5]

对象展开

let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { ...defaults, food: "rich" };

console.log(search); //输出:{food: "rich", price: "$$", ambiance: "noisy"}

对象的展开比数组的展开要复杂的多。 像数组展开一样,它是从左至右进行处理,但结果仍为对象。 这就意味着出现在展开对象后面的属性会覆盖前面的属性。 因此,如果我们修改上面的例子,在结尾处进行展开的话:

let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = {food: "rich", ...defaults };
console.log(search); //输出:{food: "spicy", price: "$$", ambiance: "noisy"}

对象展开还有其它一些意想不到的限制。 首先,它仅包含对象 自身的可枚举属性。 大体上是说当你展开一个对象实例时,你会丢失其方法:

class C {
  p = 12;
  m() {
  }
}

let c = new C();
let clone = { ...c };
clone.p; // ok
clone.m(); // error!
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页