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. Centos7更改默认启动模式(转载)

    今天心血来潮安装一个centos7的图形界面,但发现用之前的方式无法修改默认启动为命令行模式. 之前的方法:修改/etc/inittab文件中的           id:3:initdefault ...

  2. 归档NSKeyedArchiver解归档NSKeyedUnarchiver与文件管理类NSFileManager (文件操作)

    ========================== 文件操作 ========================== 一.归档NSKeyedArchiver 1.第一种方式:存储一种数据. // 归档 ...

  3. 5种处理js跨域问题方法汇总(转载)

    1.JSONP跨域GET请求 ajax请求,dataType为jsonp.这种形式需要请求在服务端调整为返回callback([json-object])的形式.如果服务端返回的是普通json对象.那 ...

  4. [Erlang 0114] Erlang Resources 小站 2013年7月~12月资讯合集

    Erlang Resources 小站 2013年7月~12月资讯合集,方便检索.     附 2013上半年盘点: Erlang Resources 小站 2013年1月~6月资讯合集    小站地 ...

  5. 从配置读取一段时间(TimeSpan)

    C#的TimeSpan表示一段时间,DateTime表示一个时间点.TimeSpan可正可负,可与DateTime相加减,很方便,我喜欢. 代码中我们经常要表示一段时间,用一个统一的单位(时 或者 分 ...

  6. Cygwin中解决vi编辑器方向键和Backspace键不好使、安装vim的方法

    修改.virc文件(如果没有就创建)vi .virc 添加以下内容set nocpset backspace=start,indent,eol 保存退出:wq 如果是vim就修改.vimrc文件. 由 ...

  7. 虚拟机+apache+php+mysql 环境安装配置

    虚拟机的安装:直接下一步即可,注意修改路径. 安装完成后新建虚拟机,直接下一步.如果选择镜像文件后出现错误,可以试着去修改电脑bios中的虚拟化设置,改为enable,如下图: apache安装: 1 ...

  8. [LeetCode] Letter Combinations of a Phone Number 电话号码的字母组合

    Given a digit string, return all possible letter combinations that the number could represent. A map ...

  9. c#连接关闭了,事务并没有关闭

    用的是mysql引擎是InnoDB,用到了连接池. 连接还没关闭,但是事务开启,并执行了更新id=14的操作,这是把这一行锁住了,可以查询,但不能更新和删除,必需等锁释放,提交换回滚事务时锁被释放.直 ...

  10. 【C#】析构函数

    MSDN paper 析构函数 析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数. 析构函数往往用来做“清理善后” 的工作( ...