浅析TypeScript
二、变量声明 及 解构赋值
如果使用过 ES6 的小伙伴,应该都知道,
解构赋值、let、const是 ES6 中的新增的特性. 因为TypeScript是JavaScript的超集,所以在TypeScript中也可以很好的使用这些语法糖.
变量声明
var 声明
- var 声明变量,变量提升 例如:
console.log(num)
var num = 10
你会发现,代码并没有报错,而是打印了 undefined . 为什么呢?
是因为 var 声明的变量存在变量提升, 代码会先声明后赋值
var num
console.log(num)
num = 10
js在执行时,就把代码解析成了上面这样,再去执行.
还有一个例子:
for(var i = 1; i < 10; i++){
setTimeout(function() {
console.log(i)
},1000)
}
// 9,9,9,9,9,9,9,9,9
你会发先打印出来的全都是9, 我们可以理解为,for 循环时,当前的代码块中只有一个变量 i 每次都去进行 ++ 操作, 遍历时,发现其中有异步操作,就继续执行循环,等循环结束, i = 9 异步操作,才执行打印了 i.
通常的做法是使用闭包, 缓存每次的数据,来解决这个问题
for(var i = 1; i < 10; i++) {
(function(i){
setTimeout(function() {
console.log(i)
},1000)
})(i)
}
// 1,2,3,4,5,6,7,8,9
这个原理,就是使用自执行函数,每次遍历都会在内存中创建一个空间,每个内存空间都有自己当前的 i 值, 所以在执行异步时, 自己当前的 i 值可以正常输出.
但这样的缺点就是, 需要在内存中开辟多个空间,导致内存泄漏.
- 重定义
使用 var 声明 重新定义变量
var n = 10
var n = 'xiaojiejie'
// 代码正常执行
这样的代码,虽然不报错,但在项目中,很容易引发其他的错误.
let 声明
现在已经发现了 var 声明的弊端了,那么来看下 let 声明
- let 声明的作用域
let 声明 跟 var 声明 类似.但 let 有自己的块级作用域, 块级作用域在包含他们的块之外是不能被访问的.
function getAge(age: number){
let teacherAge = 20
if(age < 18){
let girlAge = age + teacherAge
return girlAge
}
return girlAge
}
// age >= 18 时 grilAge is not defined
当 a >= 18 时,当前代码会报错,提示 没有找到girlAge
let 声明变量前的区域称为当前变量的死区
console.log(arr)
// arr is not defined
let arr = []
这样, console 就在 arr 的死区中执行,会导致代码报错.
let 在 for 循环中
for(let i = 1; i < 10; i++){
setTimeout(function() {
console.log(i)
},1000)
}
// 1,2,3,4,5,6,7,8,9
遍历时, 每执行一次,就会有一个代码块产生,而每个代码块中都会包含当前的 i 值,所以这个代码可以正常输出我们期望得到的值
- let 声明 的屏蔽
上面我们发现. 使用 var 声明 两个相同的变量在js中是可以允许的.但这种宽松的代码要求并不好.那么let 声明呢?
在 TypeScript 中:
let x: number = 20
let x: string = 'xiaojiejie'
// 错误, 不能在1个作用域中多次声明 x
这种行为 在ts中是完全不被允许的. 可以更好的规范我们的代码.
const 声明
const 声明, 是声明常量的一种方式.
const url: string = 'www.baidu.com'
它于 let 声明 相似. 但 const 声明的值,被赋值后就不能再次更改了.
const num: number = 123
num = 456
// 'num' has already been declared
解构赋值
数组的解构赋值
let arr: number[] = [1, 2, 3, 4]
let [one, two, three, four] = arr
console.log(one, two, three, four)
// 1 2 3 4
// 函数参数的解构
function numAdd([one, two]: [number, number]){
console.log(one, two)
}
numAdd([1, 3])
如果数组中元素过多,我们还可以使用 ... 来获取剩余元素:
let [first, ...fourth] = [1, 2, 3, 4]
console.log(first) // 1
console.log(fourth) // [2, 3, 4]
对象的解构
了解了数组的解构,再来看看对象的解构吧!
let obj:{
name: string;
age: number;
bust: number
} = {
name: 'xiaojiejie',
age: 18,
bust: 98
}
let { name, age, bust } = obj
console.log(name, age, bust)
// xiaojiejie 18 98
对象和数组都可以不用声明直接赋值:
({ a, b } = { a: 'nihao', b: 'woshimayun' })
[ first,second ] = [1, 2, 3]
在对象中,也可以使用 ... 语法来获取剩余的变量;
let obj:{
name: string;
age: number;
bust: number
} = {
name: 'xiaojiejie',
age: 18,
bust: 98
}
let { num, ...objs } = obj
函数的参数也是可以解构的:
function getName({a, b} = { a: '', b: 3 }): void {
// 代码
}
我们在解构对象或数组时,参数可以只解构部分(用哪些,就解构哪些).
展开
展开跟解构是相反的意思,也同时存在于数组和对象中:
// 数组中
let arr = [1, 2, 3]
let arr2 = [4, 5, 6]
let arr3 = [...arr,...arr2]
console.log(arr3) // [1, 2, 3, 4, 5, 6]
// 对象中
let obj: { name: string } = { name: 'mayun' }
let obj1: { age: number } = { age: 18 }
let obj3 = { ...obj, ...obj1 }
console.log(obj3)
// { name: 'mayun', age: 18 }
注意: 对象的解构,如果有相同的键名时,后解构的键值会覆盖前面的键值.
let obj: { name: string } = { name: 'mayun' }
let obj1: { age: number; name: string } = { age: 18, name: 'zhangsan' }
let obj3 = { ...obj, ...obj1 }
console.log(obj3)
// { age: 18, name: 'zhangsan' }
总结
这篇文章主要讲了:
- 变量的声明 let const
- 解构赋值(数组的解构,对象的解构)
- 展开(数组的展开,对象的展开)
我们都知道 JavaScript 的诞生只用了 10 天,难免会有一些缺陷,这些年,也一直在改进.所以,既然出了新的特性,新的方法.那就有它诞生的原因.我们不能固步自封.要敢于尝试学习新的知识.这样才能走在时代的前沿;
文章到此结束.文章只是个人的学习总结,如有什么不对的地方,请大家及时指出,让我们共同进步!!!
本文使用 mdnice 排版