我们在js下声明变量通常使用的方式var来声明变量,但偶尔也会使用const来声明常量,一般来说常量是不能被修改的,JavaScript下面,const在强制修改也是可以被修改的,但是在typescript中就不一样了,在ts中同样声明变量可以用到var,const,let(es6中)来声明一个变量,注意,在ts中通过const来声明的常量在一开始就需要给定一个值,该常量是不能被再次修改的,若强制修改,一般的编辑器都会有提示错误信息,比如

我们先来说下var声明的变量,熟悉JavaScript的都知道var的使用,它可以在外部声明,也可以在函数中声明
// 典型的闭包函数
function f() {
let a = 10;
console.log(a);//10
return function g() {
let b = a + 1;
return b;
}
}
let g = f();
console.log(g());//11
function ff(val: boolean) {
if (val) {
var a = 10;
}
return a;
}
console.log(ff(false));//undefined
console.log(ff(true));//10
看上面代码ff函数,ff(false) 之所以会返回undefined;其实ff函数代码运行如下
function ff(val:boolean){
// 通过var定义了一个变量a,但并未赋值,所以当前a的值为undefined;
var a;
if(val){
// 只有当val的值为真时,才赋值a为10;
a = 10;
}
return a;
}
function f3(){
// 定义的一个变量a
var a = 32;
// 重复定义变量a并赋值为一个函数
var a = function(){
var a = 32;
return a+2;
}
// 返回a函数
return a();
}
f3();
我们可以看到,通过var定义的变量我们在下文还可以重新赋值为其他值或是函数等,下文所赋值的函数或是值会覆盖上文的变量。
function foo() {
// 以下输出3次3
for (var i = 0; i < 3; i++) {
// 传给setTimeout的每一个函数表达式实际上都引用了相同作用域里的同一个i
setTimeout(function () { console.log(i); }, 100 * i);
}
// 要想输出0,1,2。可以通过闭包的形式来解决
for (var i = 0; i < 10; i++) {
(function (i) {
setTimeout(function () { console.log(i); }, 100 * i);
})(i);
}
}
// foo();//输出0,1,2
function foo1() {
for (let i = 0; i < 3; i++) {
setTimeout(function () { console.log(i); }, 100 * i);
}
}
上面代码我们可以看出通过let声明的变量i就不会出现输出同一个值得情况,这就是我们要说的块级作用域,通过let来声明的变量,通常我们将{}这种用大括号包含起来的代码块,我们就叫做一个块级作用域,比如上面的foo1函数,let定义的变量i在循环中每执行一次循环,就i就重新赋值了,每次循环的时候i的作用域都是不一样的,故而不会出现i值重写的情况,之所以使用var定义的变量通过for循环之后输出的值都是一样的是因为i的值都是最后一次的值。
function f1(input: true) {
let a = 1;
if (input) {
let b = 2;
}
// return b;//此时不能被访问到,let作为块级作用域下,不能访问到if代码块中使用let定义的变量
return a;
}




//虽然说不存在变量提升,但下面这种方式编译是通过的,但是运行会抛错
function fun() {
console.log(num);
}
let num = 3;
//这就是我们常说的暂时性死区

let
vs. const
现在我们有两种作用域相似的声明方式,我们自然会问到底应该使用哪个。 与大多数泛泛的问题一样,答案是:依情况而定。
使用最小特权原则,所有变量除了你计划去修改的都应该使用const
。 基本原则就是如果一个变量不需要对它写入,那么其它使用这些代码的人也不能够写入它们,并且要思考为什么会需要对这些变量重新赋值。 使用 const
也可以让我们更容易的推测数据的流动。
解构赋值,与es6中的解构赋值基本一致
let [fir,sub] = [1,3];
console.log(fir,sub); // 1,3 ;这种赋值方式称之为解构赋值
let {b,c} = {b:4,c:6};
console.log(b,c);//b:4 c:6
let [d,...e] = [1,2,3,4,5];
console.log(d,e);//d:1,e:[2,3,4,5]
function fun1([a,b]:[number,number]){
console.log(a,b); // a:1 b:2
}
fun1([1,2]);
//解构对象
let o = {
n: "foo",
v: 12,
};
// let { n,v } = o;
// 下面这个解构跟es6中的对象解构一致,冒号前面的是o对象中的键,冒号后面的是才是所定义的变量(理解为)
let { n: h, v: j } = o;
console.log(h, j); // h:'foo' j:12
展开
展开操作符正与解构相反。 它允许你将一个数组展开为另一个数组,或将一个对象展开为另一个对象
let first = [1, 2];
let second = [3, 4];
let bothPlus = [0, ...first, ...second, 5];
这会令bothPlus
的值为[0, 1, 2, 3, 4, 5]
。 展开操作创建了 first
和second
的一份浅拷贝。 它们不会被展开操作所改变。
你还可以展开对象:
let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { ...defaults, food: "rich" };
search
的值为{ food: "rich", price: "$$", ambiance: "noisy" }
。 对象的展开比数组的展开要复杂的多。 像数组展开一样,它是从左至右进行处理,但结果仍为对象。 这就意味着出现在展开对象后面的属性会覆盖前面的属性。 因此,如果我们修改上面的例子,在结尾处进行展开的话:
let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { food: "rich", ...defaults };
那么,defaults
里的food
属性会重写food: "rich"
,在这里这并不是我们想要的结果
这里总结下所谓的展开操作,实际上与es6中的...操作符也是类似,可以算作是合并操作。
PHP Warning: curl_exec() has been disabled for security reasons in /home/ftp/f/free49568/wwwroot/wp-content/themes/Variant/functions.php on line 490 百度已收录
typescript之三(变量声明):等您坐沙发呢!