-
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量声明</title>
<script src="blsm.js"></script>
</head>
<body>
</body>
</html>
-
ts
/**
* var:之前的javascript只能通过var进行变量声明,而var声明的变量有很多缺陷
* 作用域规则:
* 1 外部可访问到内部定义的变量
* 2 变量可以在未定义的时候使用,只是值为undefined
* var声明可以在包含它的函数,模块,命名空间或全局作用域内部任何位置被访问
* 3 捕获变量的怪异之处
*/
//var 1
function f10(shouldInitialize: boolean) {
if (shouldInitialize) {
var x = 10;
}
return x;//这里没有问题,不会报错
}
console.log(f10(true));//10;
console.log(f10(false));//undefined;
//var 2
console.log('blsmname:'+blsm_name);
var blsm_name = "jack";
//let则不行
// console.log(name2);//报错:因为下面用let声明了该变量,那么声明之前的就属于暂时性死区
// let name2='jack';
//var 3
// for (var i = 0; i < 10; i++) {
// setTimeout(function() { console.log(i); }, 100 * i);
// }
//结果:10个10
//var替换为let,结果为0-9
// for (let i = 0; i < 10; i++) {
// setTimeout(function() { console.log(i); }, 100 * i);
// console.log(i);
// }
/*
* 原因分析:
* 1 每一次for循环的时候,settimeout都执行一次,但是里面的函数没有被执行,
* 而是(里面的函数)被放到了任务队列里面,当主线程执行完成后,才进入任务队列里面执行,
* 2 任务队列可分为宏任务(macro-task)和微任务(micro-task)。主线程执行完之后->执行微任务->执行宏任务(在执行某个宏任务时这个宏任务就可以当做主线程,所以和前面的顺序一样)
* XHR回调、事件回调(鼠标键盘事件)、setImmediate、setTimeout、setInterval、indexedDB数据库操作等I/O都属于宏任务
* process.nextTick、Promise.then、Object.observer(已经被废弃)、MutationObserver(html5新特性),Promise.then属于微任务
* 3 因此setTimeout的函数则会被放到任务队列中,普通代码(console.log(i))会按照主线程执行
* 4 主线已经执行完毕,所以对于var定义的变量来说,现在的i已经==10,因此输出10个10
* 5 对于let定义的变量来说:
* for循环头部的let 声明还会有一个特殊的行为。
* 这个行为指出变量在循环过程中不止被声明一次,每次迭代都会声明,
* 随后的每个迭代都会使用上一个迭代结束时的值来初始化这个变量,
* 因此,每个迭代都会声明变量,后面在function() { console.log(i); }执行的时候的i是每次迭代时所声明的,
* 最终得到值为0-9
*/
function ff10([first, second]:[number,number]) {
console.log(first);
console.log(second);
}
let input = [1, 2];
//ff(input);//这里报错只是语法报错,其实是可以这么用的,输出的结果没问题
let input2:[number,number] = [1,2];
// let [name3,age3]:[string,number] = input3;//这么定义变量是错误,变量不能是[...],都不符合变量命名规范了
//解构:
//数组解构
//1.1
let params = [1,2];
// params = [];
let [p0=100,p1]:number[] = params;//OK:可以去掉':number[]',可以使用默认值
// let [p0,p1]:[number,number] = params;//error
console.log(p0,p1);
//1.2 对于已定义的参数,可以通过解构来交换
let min = 0;
let max = 100;
console.log(min,max);//0,100
[min,max] = [max,min];
console.log(min,max);//100,0
//1.3 作为函数参数
function func([num1,num2]){
console.log(num1,num2);
}
func([2,3]);
//...:剩余的都匹配到other:[3,4,5]
params = [1,2,3,4,5];
let [first,second,...other] = params;
console.log(first,second,other);
//这样只会匹配第一个数:1
[first] = params;
console.log(first);
//或者可以匹配某几个元素
let [,two,,four,] = params;
console.log(two,four);
//对象解构
let json = {
myName:'liucai',
age:24,
sex:'man'
}
//let定义的变量名要和Json里的一样(但如果是这样:let {myName:n,age:a},这里后面是n,a都没关系,实际上是要前面的属性名对应一致)
let {myName,age} = json;//多的sex没关系
console.log(myName,age);
//利用()防止{}被当做代码块
let aa;
let bb;
({aa,bb} = {aa:'a',bb:'b'});//这里要用'()',否则直接用{}会被当做代码块,不会当做解构
console.log(aa,bb);
//...剩余变量
let o = {
a: "foo",
b: 12,
c: "bar"
};
let {a:string,...otherParam} = o;//这个地方a要指定类型,otherParam对应后面的b,c
//属性重命名:a和b对应o对象里面的属性名,然后定义的变量的名字是newName1和newName2
//也就相当于:let newName1 = o.a;let newName2 = o.b;
let { a: newName1, b: newName2 } = o;
//给变量指定类型
let json2 = {
j1:'jjj',
j2:222
}
let {j1,j2}:{j1:string,j2:number} = json2;
console.log(j1,j2);
//默认值
let json3 = {
xx:10,
yy:20
}
let {xx=0,yy=100} = json3;//如果json没值(如let json3;),则为默认值,注:let json3 = {x:10,y:20},这样不行,这里会报错,因为找不到xx,yy属性
console.log(xx,yy);
//展开操作符
//1 展开数组
let bofore = [1,2,3,4,5];
let after = [6,7,8,9,10];
let num = [0,...bofore,...after];
console.log(num);//[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
//展开对象
let jsonObj = {
name:'wanglin',
age:1423346,
height:222
}
let newJson = {name:'suming',...jsonObj};
console.log(newJson);//{name: "wanglin", age: 1423346, height: 222}--前面的name属性值会被后面的覆盖掉
//使用...展开class时,会丢失方法
class C {
constructor(){
}
name:string = 'CCC';
showName(){
console.log(this.name);
}
}
let newC = new C();
console.log(newC.name);
newC.showName();
let newCC = {...newC};//对构造的class对象进行解构
console.log(newCC.name);//调用不到showName()方法了