1.let和const命令
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
上面代码中,变量i是var声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的function在运行时,会通过闭包读到这同一个变量i,导致最后输出的是最后一轮的i的值,也就是10。
console.log(a)//[function(){console.log(i)},function(){console.log(i)},function(){console.log(i)}]
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
for(let i=0;i<3;i++)
{
let i="abc"
console.log(i)
}
//"abc"
//"abc"
//"abc"
说明内部变量不会影响到外部变量
function bar(x=y,y=2)
{
return [x,y]
}
bar()//报错,y没有申明
function bar(x=2,y=x)
{
return [x,y]
}
bar()//[2,2]
2.不允许重复申明
let 不允许在相同作用域内,重复声明同一个变量
//报错
function(){
let a=10;
var a=1;
}
//报错
function(){
let a=10;
let a=1;
}
不能在函数内部重新声明参数
function func(arg)
{
let arg;//报错
}
function func(arg)
{
{
let arg;//不报错
}
}
3.块级作用域与函数申明
1.允许在块级作用域内声明函数。
2.函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
3.同时,函数声明还会提升到所在的块级作用域的头部。
function f(){
console.log('i am outside!')}]
(function(){
if(false){
function f(){
console.log('i am inside')}
}
f()
}())
//error:f is not a function
实际运行的是如下代码:
//浏览器的es6环境
function f() {
console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() {
console.log('I am inside!'); }
}
f();
}());
//浏览器的es5环境//函数会提升到函数的头部
function f(){
console.log("i am outside!")}
(function (){
function f(){
console.log("i am inside!")}
if(false){
}
f()
}())
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
// 函数声明语句
{
let a = 'secret';
function f() {
return a;
}
}
// 函数表达式
{
let a = 'secret';
let f = function () {
return a;
};
}
4.const
const声明的常量,也与let一样不可重复声明。
var a=1;
window.a//1
let b=1;
window.b//undefined
上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。
变量的解构赋值
1.设置默认值
let [foo==true]=[];
foo//true
let [x,y='b']=['a']//x='a',y='b'
let [x,y='b']=['a',undefined]//x='a',y='b'
注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。
let [x=1]=[undefined];//x//1
let [x=1]=[null]//x=null
2.对象的解构赋值
let {
bar,foo}={
foo:"aaa",bar:"bbb"}
foo//'aaa'
bar//'bbb'
let {
baz}={
foo:"aaa"