01-变量新增

nobility 发布于 2022-07-24 02-ES6 971 次阅读


变量新增

变量的定义

Let

  • 在全局定义的变量不在属于全局对象的属性
var a = {};
console.log(this.a === a);  //true
let b = {};
console.log(this.b === b);  //false
  • 具有块级作用域
let i = 0;
{
    console.log(i); //0
    i++;
}
console.log(i); //1
//相当于
let i = 0;
{
    let iCopy = i;
    console.log(iCopy); //0,使用内层的
    i++;    //修改外层的
}
console.log(i); //1

/*由上述就可得知循环中的块级作用域*/
var a = [];

for (let i = 0;i < 2; i++) {
    a[i] = function () {
        console.log(i);
    };
}
a[1](); //1
a[0](); //0
//相当于
for (let i = 0;i < 2;) {
    let iCopy = i;
    a[iCopy] = function () {
        console.log(iCopy); //使用内层的
    };
    i++;    //修改外层的
}
a[1](); //1
a[0](); //0
  • 块级作用域必须有大括号
/*像一些条件循环语句中若只有一条语句可以省略大括号,这种情况下会若使用let则必须声明大括号,否则会报错*/
for(let i = 0; i < 1; i++)
    let a = 10; //SyntaxError
if(true)
    let a = 10; //SyntaxError
  • For 循环中的父子级作用域
for (let i = 0; i < 3; i++) {   //小括号中的父作用域
    let i = 1;  //大括号是子作用域
    console.log(i); //1,三次循环都输出1
}
  • 不存在变量提升
console.log(a); //undefined
var a = 2;

console.log(b); //ReferenceError
let b = 2;
  • 不能在同一作用域下重复声明同一个变量
let a;
let a = 0;  //SyntaxError

let a;
var a = 0;	//SyntaxError

function func(arg) {	//只有运行时才会发现是否重复定义了同名变量,所以函数不调用是不会报错的
    let arg;    //SyntaxError
}
func();
  • 拥有暂时性死区(temporal dead zone):指的是使用 let 关键字定义变量时,会在该语句到该作用域的开始这部分无法使用该变量
//TDZ开始
tmp = 'abc'; //ReferenceError
console.log(tmp); //ReferenceError
let tmp;

//TDZ结束
console.log(tmp); //undefined
tmp = 1;
console.log(tmp); //1

/*
隐藏的暂时性死区
对于一些像赋值语句表达式是右结合性的,所以会先执行右部
*/
let a = a;	//ReferenceError
//相当于
//TDZ开始
a;	//ReferenceError
let a = a;
//TDZ结束

let a = b, b = 1;
//相当于
//TDZ开始
b;	//ReferenceError
let a = b;
let b = 1;
//TDZ结束

let a = 1 ,b = a;
//相当于,所以不会报错
//TDZ开始
let a = 1;
//TDZ结束
let b = a;

Const

同样具有 let 命令所有的性质:

  • 在全局定义的常量不在属于全局对象的属性
  • 具有块级作用域
  • 块级作用域必须有大括号
  • 不存在变量提升
  • 不能在同一作用域下重复声明同一个变量
  • 拥有存在暂时性死区

只不过比 let 多了一条

  • 使用该关键字声明的变量值无法改变,所以声明时必须赋值(同其他语言若常量是引用数据类型则至少引用地址不可改变)

变量的解构赋值

数组解构赋值

基本用法:[...变量] = 数组

  • 从数组对应位置为变量数组中的相应变量赋值
  • 若为匹配到的模式则会返回 undefined 或空数组
  • 可以为每个解构的变量赋予默认值,若未匹配到或这个位置的值是 undefined 则采用默认值
/*有了解构赋值就又多了一种方式交换两个变量的值*/
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b); //2 1

/*定义同时解构*/
let [a,b] = [1,2];
console.log(a,b);	//1 2
/*先定义后解构*/
let a, b;
[a, b] = [1, 2];
console.log(a, b);	//1 2
/*嵌套解构*/
let [a, [b]] = [1, [2]];
console.log(a, b);	//1 2
/*部分解构*/
let [a] = [1, 2];
console.log(a);	//1
let [,b] = [1, 2];
console.log(b);	//2
/*可变参数解构*/
let [a, ...b] = [1, 2, 3];
console.log(a, b);   //1 [ 2, 3 ]

/*未匹配到的*/
let [a, b, ...c] = [1];
console.log(a, b, c);	//1 undefined []

/*默认值*/
let [a ,b = 1] = [1];	//对为匹配到的采取默认值
console.log(a ,b);	//1 1

let [a ,b = 1] = [1, undefined];	//对undefined采取默认值
console.log(a ,b);	//1 1

let [a ,b = 1] = [1, null];	//只对undefined采取默认值
console.log(a ,b);	//1 null

let [a = 1 ,b = a] = [];	//以a的值作为b的默认值
console.log(a ,b);	//1 1

let [a = 1 ,b = a] = [2];   //此时b的默认值是拿到的a已经解构的值,而不是a定义的默认值
console.log(a ,b);	//2 2

let [a = 1 ,b = a] = [2 ,3];    //赋值后此时不会采用默认值
console.log(a ,b);  //2 3

对象的解构赋值

基本用法:{...属性: 变量} = 对象,当属性名和变量名同名时 {...变量} = 对象

  • 由于对象没有次序,所以依靠对象的属性名来确定为那个变量赋值相应的属性,可以解构继承的属性
  • 若为匹配到的模式则会返回 undefined 或空对象
  • 可以为每个解构的变量赋予默认值,若未匹配到或这个位置的值是 undefined 则采用默认值
/*定义同时解构*/
let { a: a, b: b } = { a: 1, b: 2 };
console.log(a, b);  //1 2
//可以简写为
let { a, b } = { a: 1, b: 2 };
console.log(a, b);  //1 2
//若属性名与变量名不同时不能简写,否则会匹配不到
let { a: a1, b: b1 } = { a: 1, b: 2 };
console.log(a1, b1);    //1 2
//不是按照位置,而是按照属性,所以匹配不到返回undefined
let { a1, b1 } = { a: 1, b: 2 };
console.log(a1, b1);    //undefined undefined
/*先定义后解构*/
let a, b;
{ a, b } = { a: 1, b: 2 };	//报错,SyntaxError,会当作代码块来解析
({ a, b } = { a: 1, b: 2 });	//使用小括号包裹,不要将大括号开头即可
/*嵌套解构*/
let { a, n: { b } } = { a: 2, n: { b: 3 } };    //此时n是匹配模式,而不是变量
console.log(a, b);  //2 3

let { a, p: { b } } = { a: 2, n: { b: 3 } };    //此时p匹配模式不存在,则会报错 TypeError
console.log(a, b);  //2 3
/*解构继承属性*/
let { toString } = { };    //可以解构继承的属性
console.log(toString);  //[Function: toString]
/*部分解构*/
let { b } = { a: 1, b: 2 };
console.log(b);
/*可变参数解构*/
let { a, ...b } = { a: 1, b: 2 };
console.log(a, b);  //1 { b: 2 }

/*未匹配到的*/
let { a, b, ...c } = { a: 1 };
console.log(a, b, c);  //1 undefined {}

/*默认值*/
let { a, b = 1 } = { a: 1 };	//对为匹配到的采取默认值
console.log(a, b);  //1 1

let { a, b = 1 } = { a: 1 ,b: undefined};	//对undefined采取默认值
console.log(a, b);  //1 1

let { a, b = 1 } = { a: 1 ,b: null};	//只对undefined采取默认值
console.log(a, b);  //1 null

let { a = 1, b = a } = {};	//以a的值作为b的默认值
console.log(a, b);  //1 1

let { a = 1, b = a } = { a: 2 };	//此时b的默认值是拿到的a已经解构的值,而不是a定义的默认值
console.log(a, b);  //2 2

let { a = 1, b = a } = { a: 2 ,b: 3 };	//赋值后此时不会采用默认值
console.log(a, b);  //2 3

原始数据类型的解构赋值

原始数据类型会先转化为对应的包装对象后进行解构操作

  • 字符串既可以使用数组方式解构单个字符,也可以使用对象方式解构字符串上的方法和属性
let [a, b] = "ab";
console.log(a, b);   //a b
let { length } = "ab";
console.log(length);    //2
  • 数值和布尔类型的只能使用对象解构他们转化成包装对象上的方法
let { toString } = 123;
console.log(toString === Number.prototype.toString); //true

let { toString } = true;
console.log(toString === Boolean.prototype.toString); //true

函数参数解构赋值

/*为函数参数指定默认值*/
function add(a = 1, b = 1) {
    console.log(a + b);
}
add();   //2
add(1, 2);   //3
  • 数组解构
let arr = [1, 2];
/*对传入的数组解构*/
function add([a, b]) {
    console.log(a + b);
}
add();	//TypeError,为传入参数则是对undefined解构,则无法解构就会报错
add(1, 2);  //TypeError,传入非数组无法解构就会报错
add(arr);   //3

/*对传入的数组解构,并指定解构默认值*/
function add([a, b=100]) {
    console.log(a + b);
}
add([1]);   //101
add(arr);   //3

/*对传入的数组解构,若未传入参数则解构默认数组*/
function add([a, b] = [1, 1]) {
    console.log(a + b);
}
add();  //2
add(arr);   //3
  • 对象解构
let obj = { a: 1, b: 2 };
/*传入对象进行解构*/
function show({ a, b }) {
    console.log(a, b);
}
show();	//TypeError,为传入参数则是对undefined解构,则无法解构就会报错
show(1);  //undefined undefined 不会像解构数组那样无法解构就报错,而是将原始数据类型转化成包装对象解构,匹配不到就是undefined
show(obj);   //1 2

/*对传入的对象解构,并指定解构默认值*/
function show({ a = 100, b = 100 }) {
    console.log(a, b);
}
show({});   //100 100  解构对象中没有该属性就会使用默认值
show(obj);   //1 2
/*对传入对象解构,若未传入参数则解构默认对象*/
function show({ a, b } = { a: 100, b: 100 }) {
    console.log(a, b);
}
show(); //100 100   未传入参数解构默认对象
show({});   //undefined undefined  匹配不到就是undefined
show(obj);   //1 2
加油啊!即便没有转生到异世界,也要拿出真本事!!!\(`Δ’)/
最后更新于 2022-07-24