变量声明 及 解构赋值
如果使用过 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 排版