ES6自读-let和const

ES6新增let 和 const,这里记录一些疑难点理解的思路。


let声明的变量,只在当前代码块中生效,很适合用在for循环上

for(let i = 0; i < 10; i++) {
   console.log(i);
}
console.log("代码块外", i);

代码块外会报错,这里注意,let定义的i只在本轮循环生效,每轮循环的i都是不同的,但是计算循环的值是JS引擎在上一轮的基础上进行计算的,所以不会遗忘上一轮的值而无法计算下一轮的值。

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}

上面这一段会输出3个abc,是因为for循环存在两个作用域,一个是定义循环变量的父级作用域,一个是循环体内部的子作用域。


变量提升即是未定义也能输出undefined:

console.log(a);
var a = 1;

这时候会输出undefined,脚本运行变量已存在,但是未赋值。

console.log(a);
let a = 1;

这时候输出的错误就是ReferenceError(引用未存在的变量错误)。

总而言之,言而总之,就是定义了再用,不要搞那么多骚操作。


下面记录一个大头问题,我也不知道算理解没有。。总之遇到的话应该能够识别解决吧。

暂时性死区:

块级作用域中只要存在,那么它所声明的变量就绑定该代码块,不受外部影响。

var a = 123;

if (true) {
  a = 1; 
  let a;
}

像这块,if代码块中的let a让变量a绑定了该代码块,所以进行赋值的时候他并不能取到代码块外的a,即是在赋值之前加入console语句也打印不了,被锁死在了这块代码块中。

var temp = '123';if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

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

  tmp = 123;
  console.log(tmp); // 123
}

这一段,死区(TDZ)到tmp的let定义结束,之前都是死区,任何对temp的操作都会报出 ReferenceError,只有在定义之后才能使用。

// 不报错
var x = x;

// 报错
let x = x;
// ReferenceError: x is not defined

这一段放在一起执行的话会提醒重复定义(处在同一代码块)。。所以分开来执行,第一句的话是不会报错的,第二句用let声明的就会出问题了,相当于 let x = {x}; 这样将x锁死在了代码块中,而赋值的x并没有定义,所以会抛出错误。


块级作用域:

注意代码块层级关系

(function a(){
    let b = 5;
    if(b == 5) {
        let c = b * 2;
    }
    console.log(c);
})()

这里会报C未定义,主讲这里的匿名函数。

这个函数相当于:

function a(){
    let b = 5;
    if(b == 5) {
        let c = b * 2;
    }
    console.log(c);
}
a();

块级作用域出现后,就不用这么写了,而是如下

{
    let tmp = 1;
    console.log("块级作用域" + tmp)
}

(function() {
    let tmp = 1;
    console.log("IIFE" + tmp)
})();

同时,ES6的块级作用域支持声明函数,

{
    function f() {
        console.log('2333');
    }
    let a = 1;
    let c = function() {
        return a;
    }
}

只执行一次的函数可以这么做,需要多次调用则提取至公共区域。


const声明的变量不能改变,在所定义的块级作用域中生效,存在暂时性死区,不能重复定义,对于简单的数据类型,const声明的变量指向的内存地址存储的便是值本身;对于复合数据(对象、数组...),变量指向的内存地址,保存的是一个指针,指针固定,但其指向的数据结构不确定,如果存储的是一个对象,我们可以对对象的属性进行编辑:

{
    const a = {};
    a.name = "Tom";
    console.log(a.name);
}
数组的话我们可以对其定义的本身的数组进行增删操作,却不能将另一个数组再次赋值给声明的变量。


顶层对象:浏览器中指的是window对象,在node中是global对象,ES5中,顶层对象‘属性’和全局变量等价。

顶层对象属性和全局变量等价带来了许多问题,最典型的便是我们只有在运行后才知道变量的未声明错误,不能在编译期就报错,是因为全局变量可能是顶层对象属性创建的,而属性的创建是动态的。

到了ES6,let、const命令声明的变量不属于顶层对象的属性,但是var和function仍是:

var a = 1;
console.log(window.a);

const b = 1;
console.log(window.b);
第一个打印能打印出1,第二个undefined。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值