1、 let与const
常量const [常量声明的时候要赋值;常量是不能被修改的,但可以修改对象的值。因为对象是引用类型,const 指向的是对象引用地址,只要地址不变就符合 const 定义]
Es5写法
Object.defineProperty(window,”PI2”,{
value: 3.1415926,
writable: false
})
Es6写法: const PI = 3.1415926
变量let let a = 1 [let声明的变量只在块作用域有效;es6强制开启严格模式,变量未声明不能引用,否则会报引用错误;let不能重复定义变量]
functiontest(){for(leti=1;i<3;i++){console.log(i);//1 2}console.log(i);//uncaught ReferenceError: i is not defined//let a = 1;leta=2;}functionlast(){constPI=3.1415926;constk={a:1}k.b=3;console.log(PI,k);}test();last();
2、解构赋值
什么是解构赋值:语法上就是赋值的作用。
解构:左边一种结构,右边一种结构,左右一一对应进行赋值。
解构赋值的分类:
数组解构赋值、对象解构赋值、字符串解构赋值、布尔值解构赋值、函数参数解构赋值、数值解构赋值
1)数组结构赋值
{leta,b,rest;[a,b]=[1,2];//let a=1,b=2;之前的写法console.log(a,b);//1 2}
... 可以把其它的归为一个数组
{leta,b,rest;[a,b,...rest]=[1,2,3,4,5,6];console.log(a,b,rest);//1 2 [3,4,5,6]}
延伸:可以给c赋值为默认值,防止没有成功配对赋值时候值为undefind情况
{leta,b,c,rest;//[a,b,c]=[1,2];[a,b,c=3]=[1,2];//console.log(a,b,c);//1 2 undefinedconsole.log(a,b,c);//1 2 3}
在es5中不好实现的代码,可以通过结构赋值轻松解决,如下
变量交换
{leta=1;letb=2;[a,b]=[b,a];console.log(a,b);//2 1}
取函数return回来的值
{functionf(){return[1,2]}leta,b;[a,b]=f();console.log(a,b);//1 2}
当函数返回多个值时,可以选择性的去接收某几个变量
{functionf(){return[1,2,3,4,5]}leta,b,c;[a,,,b]=f();console.log(a,b);//1 4}
不知道返回数组的长度时,后面的数可以接收为数组
{functionf(){return[1,2,3,4,5]}leta,b,c;[a,,...b]=f();console.log(a,b);//1 [2,3,4,5]}
2)对象解构赋值
{leta,b;({a,b}={a:1,b:2})console.log(a,b);//1 2}
{leto={p:42,q:true};let{p,q}=o;console.log(p,q);//42 true}
对象解构赋值的默认值处理
{let{a=10,b=5}={a:3};console.log(a,b);}
对象解构赋值场景:
{
let metaData={
title:'abc',
test:[{
title:'test',
desc:'description'
}]
}
let {title:esTitle,test:[{title:cnTitle}]}=metaData;
console.log(esTitle,cnTitle);
}
1.var可以重复声明
var a = 12;
var a = 5;
alert(a) //5
2.var无法限制修改
如:PI = 3.1415;
3.var没有块级作用域
{
}
像:
if(){}for(){}
这都是块级作用域,在这里面定义的变量则在块级域外面是没法使用的。
4.let和const不能重复声明
let a =12;
let a=5;
alert(a)//报错
const a =12;
const a=5;
alert(a)//报错
5.let是可以重复修改的,但是const是常量,是不能重复修改的。
let a = 12;
a = 5;
alert(a); //5
const a = 12;
a = 5;
alert(a);//报错
6.块级作用域
if(true){
let a = 12;
}
alert(a);//报错,a is not defined
if(true){
const a = 12;
}
alert(a);//报错,a is not defined
语法快不仅仅是if,for等这些,如下面的也是块级作用域:
{
let a = 5;
console.log(a) //5
}
console.log(a); //报错,a is not defined
7.块级作用域的用法:
现在有三个button,分别点击,传统的写法是:
window.onload =function(){varaBtn =document.getElementByTagName("input");for(vari=0;i
结果每次弹出的都是3,然后我们采用函数作为块级作用域的方式在外边增加一层,如下:
window.onload =function(){varaBtn =document.getElementByTagName("input");for(vari=0;i
虽然问题解决了,但是如果用现在ES6的let,本身就是在块级作用域中有效,更加方便;
window.onload =function(){varaBtn =document.getElementByTagName("input");for(leti=0;i
最后总结如下:
名称 重复声明 修改 块级作用域
let 不能重复声明 变量可以修改 块级作用域
const 不能重复声明 常量不可以修改 块级作用域
一、let命令
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
for循环的计数器,就很合适使用let命令。
for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域
for(let i =0; i <3; i++) {
let i ='abc';
console.log(i);
}//abc//abc//abc
上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域.
// var 的情况console.log(a);// 输出undefinedvara =2;// let 的情况console.log(a);// 报错ReferenceErrorlet a =2;
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
if(true) {
// TDZ开始tmp ='abc';// ReferenceErrorconsole.log(tmp);// ReferenceError let tmp; // TDZ结束console.log(tmp);// undefined tmp =123;
console.log(tmp); // 123}
错误实例:
//错误实例1 vara1 ='123'; if(true){
a1 ='456';//出现了let所以if内生成了一个单独的封闭作用域,而a1在还未let声明前使用会报错 let a1;
};//错误实例2let x1 = y1, y1 =1;
function fn(){
console.log(x1,y1);//y1在let未声明前使用报错
};
fn();
注意:“暂时性死区”也意味着typeof不再是一个百分之百安全的操作。
a是一个不存在的变量名,结果返回“undefined”。
console.log(typeofa);//undefined
let a =10;
let a =1;//报错
二、const命令
const声明一个只读的常量。一旦声明,常量的值就不能改变。相同: 与let 作用域 块级作用域
constPI =3.1415;
PI // 3.1415PI =3;// TypeError: Assignment to constant variable.
实例:
consta =true;//字符串 数值 布尔//数组constarr =[];//arr指向的是一个内存地址
arr.push('123');
console.log(arr);//对象constobj = {};
obj.name ='abc';
console.log(obj);//注意 不能只申明不赋值 申明后一定要初始化,不能以后赋值const w;
console.log(w); //错误