Let & Const

let 基础用法

很简单就能说明这个问题

if(false)
{
    var a = 'heihei'
}
a = undefined

if(true) {
    var a = 'heihei'
}
a = heihei

也就是说. { } 是木有作用域的.

里面声明的外面依然能够访问.

if(true) { let b = 'heihei_b' }
b = undefined

这样就有作用域了.

我想 w3c 如果不是为了兼容老代码。 可能直接强制用var 也遵循 代码块有作用域吧.

例子

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6]();  //6

这个是文章中的一个列子.

书中的解释是

上面代码中,变量ilet声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。

也就是说。 每一次都是一个新的循环,

对于新的循环来说 i 就是新的局部变量.

不存在变量提升

首先得明白什么是变量提升.

var a = 'haha';
(function() {
  alert(a)
})();

会弹出 haha

var a = 'haha';
(function() {
  var a = 'haha inside';
  alert(a);
})()

这个就是 haha inside 因为你调用的是局部变量 a.

var a = 'haha';
(function() {
  alert(a);
  var a = 'haha inside';
})()

这个时候弹出来 undefined

其实这段代码相当于

var a = 'haha';
(function() {
  var a;
  alert(a);
  a = 'haha inside';
})()

这个就是变量提升.

书中的不会存在变量提升就是指.

我不会弹出 undefined 哟.

我会报错. xxxx is not defined

就是这个意思.

暂时性死区

let 或 const 声明的变量拥有暂时性死区(TDZ):当进入它的作用域,它不能被访问(获取或设置)直到执行到达声明。

首先暂时性死区 就是变量提升的另一种说法.

var a = 'haha';
(function() {
  alert(a);
  var a = 'haha inside';
})()

这个之所以会弹出. undefined 是因为 var a = 'haha inside';

相当于在自执行函数顶部声明了一个 var a; 然后后面来赋值.

使用 let or const 你在声明之前使用会报错

不管你是否去 typeof

避免了 变量提升 的危险.

这个区域 就有一个吊炸天的名字 暂时性死区

本质就是叫你 别提莫 声明之前去使用.

不允许重复声明

var a = 1;
var a = 2;

var 可以重复声明。 谁后面声明用谁.

但是 let or const 不行.

不管对方使用的 var or let or const

以下情况都会报错

var a;
let a;

var b;
const b = '2';

let c;
var c;

const d = '2';
var d;

以上仅针对于同一级别的作用域。

块级作用域

以前 javascript 并没有块级作用域. 也就是说.

var a = 'b';
if(true)
    var a = 'c' 

a 等于 c

也就是说. 你 if 中声明的任何变量.

都将是和if同一层级的变量.

谈不上坑爹. 可是毕竟很多时候是需要块级作用域

要不也不用每次都写匿名自执行的函数

var a = (function(){ var a = ''; })();

难免会有污染的情况

还有书中说的.

for(var i=0;i<10;i++)
{

}

console.log(i); //10.

由于没有块级作用域. 所以泄露到了外部.

书中还提到了变量提升

var tmp = new Date();

function f() {
  console.log(tmp);
  if (false) {
    var tmp = "hello world";
  }
}

f(); // undefined

其实。 有良好的书写习惯的话 这种问题很少遇到.

当你使用 let or const 的时候就没有这种烦恼.

for(let i=0;i<10;i++)
{

}

console.log(i); // undefined

任意嵌套也没问题

for(let i=0;i<10;i++)
{
    if(true)
    {
        let i = 'wao';
    }

    console.log(i); // 1,2,3,4,5...
}

不同的 {} 就是一个作用域.

这引申出几个问题.

一. 是否是 {} 就是一个作用域。 switch case 呢?

function switchTest(o) {
    switch(o)
    {
      case '1':
        let a = '1';
        break;
      case '2':
        let a = '2';
        break;
    }
}

然后并不可以 直接报错.

Identifier 'a' has already been declared

继续来

function switchTest(o) {
    switch(o)
    {
      case '1':
        let a = '1';
        break;
      case '2':
        let b = '2';
        break;
    }

    console.log(a);
    console.log(b);
}

不管怎么都会报错.

因为变量死区.

就算你只输出一个 例如

console.log(a); //undefined

然而 真的有块级作用域

顺便提一句.

switch case 是一个很神奇的东西.

你在其中声明一样的变量,他会告诉你 变量已经声明过了. 一副我们里面是一起的样子

可是呢.

它和if有相同的功能.

如果没有 case 到. 那么里面代码也是不会执行.

如果你用var 该泄露还是泄露..

二. 书中提到的. function

首先书中提到了几个东西.

  1. es5 中不允许在 块级作用域 中声明函数
  2. es6 中. 允许声明,并且是类似 let 的行为,外部不能访问.

然而并没有声明卵用..

ES5. 浏览器没有遵守这个规定,还是支持在块级作用域之中声明函数。

而且 es5 & es6 混杂的情况下. 也很难按照规定来做.

以下是我测试. chrome 51.

目测只要执行过的 function 是不会遵循es6 let 声明.. 外部都能访问.

try {
  function f() {}
}
catch(e) { }

if (true) {
  function f() {}
}

都会影响外部.

如果不执行. 就没有这个问题.

如果在 function 中声明函数。 是不会影响外部的.

有点儿类似于 是声明的表达式.

可是有一个奇葩的

function f() { console.log('I am outside!'); }
(function () {
  if (false) {
    function f() { console.log('I am inside!'); }
  }

  f();
}());

按照我刚才的说法.

应该是执行 i am outside. 毕竟没有执行.

可是 ie9 是 I am inside! 如果在外部调用。 依然是 I am outside!'

chrome 是直接报错. 在外部 I am outside!'

然后茫然不知所措.

只能说各个浏览器,解析的方式各有不同.

考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

三. 块级作用域

之前突发奇想. 如果在一个里面,同事使用 let & var

是不是 外部能访问 b 不能访问 a

if(true) {
    var b = 'b';
    let a = 'a'
}

是可以的.

也就是说. 所谓的块级作用域其实和 {} 无关.

你必须使用 let 罢了

const

可以说他就是一个 固定的 let

const a;

你必须一开始就赋值. 不然会报错.

赋值以后,如果是值类型是不能更改的.

const a = 1;
a = 2

这样是会报错的.

可是引用类型就不一样了.

const 只能保证在 栈内存上的地址是不变的.

也就是说.

const a = {};
a['b'] = 'b';

这样是ok的.

内存地址不变,可是堆内存的实际的东西发生了变化.

如果你这样直接硬来是不行的。

const a = {};
a = {}

因为你这样是会改变地址的..

所以。

const 就用开放放字符串,数值吧.

全局对象的属性

如果你这样写.

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

也就是说 var 在顶层声明会自动成为 window 属性.

但是 let 不会..

就是这样..

如果你用全部用 let

作用域就是 window -> 1层 -> 2层.

var

就是 (window & 1层) > 2层..

以上.

thx

02. Let & Const的更多相关文章

  1. ES6入门笔记

    ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...

  2. 我们为之奋斗过的C#-----C#的一个简单理解

    我们首先来简单叙述一下什么是.NET,以及C#的一个简单理解和他们俩的一个区别. 1 .NET概述 .NET是Microsoft.NET的简称,是基于Windows平台的一种技术.它包含了能在.NET ...

  3. Koa 框架教程

    Koa 框架教程   作者: 阮一峰 日期: 2017年8月 9日 Node 主要用在开发 Web 应用.这决定了使用 Node,往往离不开 Web 应用框架. Koa 就是一种简单好用的 Web 框 ...

  4. [React] 06 - Route: koa makes your life easier

    听说koa比express更傻瓜化,真的? Koa 框架教程 本身代码只有1000多行,所有功能都通过插件实现,很符合 Unix 哲学. 搭建简单服务器 Koa, 架设一个简单的服务器 // demo ...

  5. Koa框架教程

    Node主要用在开发 Web 应用.这决定了使用 Node,往往离不开 Web 应用框架. Koa 就是一种简单好用的 Web 框架.它的特点是优雅.简洁.表达力强.自由度高.本身代码只有1000多行 ...

  6. 深入剖析 linux GCC 4.4 的 STL string

    转自: 深入剖析 linux GCC 4.4 的 STL string 本文通过研究STL源码来剖析C++中标准模板块库std::string运行机理,重点研究了其中的引用计数和Copy-On-Wri ...

  7. string源码分析 ——转载 http://blogs.360.cn/360cloud/2012/11/26/linux-gcc-stl-string-in-depth/

    1. 问题提出 最近在我们的项目当中,出现了两次与使用string相关的问题. 1.1. 问题1:新代码引入的Bug 前一段时间有一个老项目来一个新需求,我们新增了一些代码逻辑来处理这个新需求.测试阶 ...

  8. 目标检测之harr---角点检测harr 的opencv实现

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/29356187 作者:毛星云(浅墨) ...

  9. sizeof 感知重载,模板具现, 转换规则

    问题:如何侦知任意型别 T 是否可以自动转换为型别 U? 方案:侦测转换能力的想法:合并运用 sizeof 和重载函数. 1 依赖 sizeof,sizeof 有着惊人的能力,你可以把 sizeof  ...

随机推荐

  1. UITextField

    UITextFieldDemo 效果 特点 1.有效定制键盘的样式 2.处理键盘对文本框的遮挡 用法 1.导入文件(UITextField+CreateInputAccessoryView.h/.m) ...

  2. Hibernate 系列 02 - Hibernate介绍及其环境搭建

    引导目录: Hibernate 系列教程 目录 昨晚喝多了,下午刚清醒,继续搞Hibernate.走起. 觉得还行的话,记得点赞哈,给我这个渣渣点学习的动力.有错误的话也请指出,省的我在错误上走了不归 ...

  3. [AlwaysOn Availability Groups]监控AG性能

    监控AG性能 AG的性能的性能方面,在关键任务数据库上进行语句级维护性能是很重要的.理解AG如何传输日志到secondary副本对评估RTO和RPO,表明AG是否性能不好. 1. 数据同步步骤 为了评 ...

  4. MySQL Performance-Schema(二) 理论篇

    MySQL Performance-Schema中总共包含52个表,主要分为几类:Setup表,Instance表,Wait Event表,Stage Event表Statement Event表,C ...

  5. python-运算符

    1.算数运算: 2.比较运算: 3.赋值运算:   4.逻辑运算: 5.成员运算: 本文转载自http://www.cnblogs.com/wupeiqi/articles/5444685.html

  6. Jsoup系列学习(2)-解析html文件

    解析html文件 1.当我们通过发送http请求时,有时候返回结果是一个html格式字符串,你需要从一个网站获取和解析一个HTML文档,并查找其中的相关数据.你可以使用下面解决方法: 使用 Jsoup ...

  7. 使用Flask设计带认证token的RESTful API接口[翻译]

    上一篇文章, 使用python的Flask实现一个RESTful API服务器端  简单地演示了Flask实的现的api服务器,里面提到了因为无状态的原则,没有session cookies,如果访问 ...

  8. Windows 10下使用U盘安装Ubuntu双系统

    问题描述:在Windows10下安装Ubuntu. 使用工具:Windows10.Ubuntu16.04 LTS安装包.UltraISO.easyBCD. 操作步骤: 1.安装之前要给Ubuntu分出 ...

  9. Installation error: INSTALL_FAILED_NO_MATCHING_ABIS

    使用Genymotion调试出现错误INSTALL_FAILED_CPU_ABI_INCOMPATIBLE解决办法 http://www.cnblogs.com/xiaobo-Linux/ 下载地址: ...

  10. [bzoj1269][AHOI2006文本编辑器editor] (splay模版题 or pb_ds [rope]大法)

    Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或 ...