02. Let & Const
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
这个是文章中的一个列子.
书中的解释是
上面代码中,变量
i是let声明的,当前的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
首先书中提到了几个东西.
- es5 中不允许在 块级作用域 中声明函数
- 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的更多相关文章
- ES6入门笔记
ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...
- 我们为之奋斗过的C#-----C#的一个简单理解
我们首先来简单叙述一下什么是.NET,以及C#的一个简单理解和他们俩的一个区别. 1 .NET概述 .NET是Microsoft.NET的简称,是基于Windows平台的一种技术.它包含了能在.NET ...
- Koa 框架教程
Koa 框架教程 作者: 阮一峰 日期: 2017年8月 9日 Node 主要用在开发 Web 应用.这决定了使用 Node,往往离不开 Web 应用框架. Koa 就是一种简单好用的 Web 框 ...
- [React] 06 - Route: koa makes your life easier
听说koa比express更傻瓜化,真的? Koa 框架教程 本身代码只有1000多行,所有功能都通过插件实现,很符合 Unix 哲学. 搭建简单服务器 Koa, 架设一个简单的服务器 // demo ...
- Koa框架教程
Node主要用在开发 Web 应用.这决定了使用 Node,往往离不开 Web 应用框架. Koa 就是一种简单好用的 Web 框架.它的特点是优雅.简洁.表达力强.自由度高.本身代码只有1000多行 ...
- 深入剖析 linux GCC 4.4 的 STL string
转自: 深入剖析 linux GCC 4.4 的 STL string 本文通过研究STL源码来剖析C++中标准模板块库std::string运行机理,重点研究了其中的引用计数和Copy-On-Wri ...
- string源码分析 ——转载 http://blogs.360.cn/360cloud/2012/11/26/linux-gcc-stl-string-in-depth/
1. 问题提出 最近在我们的项目当中,出现了两次与使用string相关的问题. 1.1. 问题1:新代码引入的Bug 前一段时间有一个老项目来一个新需求,我们新增了一些代码逻辑来处理这个新需求.测试阶 ...
- 目标检测之harr---角点检测harr 的opencv实现
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/29356187 作者:毛星云(浅墨) ...
- sizeof 感知重载,模板具现, 转换规则
问题:如何侦知任意型别 T 是否可以自动转换为型别 U? 方案:侦测转换能力的想法:合并运用 sizeof 和重载函数. 1 依赖 sizeof,sizeof 有着惊人的能力,你可以把 sizeof ...
随机推荐
- 集成shareSDK错误总结(新浪微博)
错误1. . 以上错误是由于没有添加-ObjC的原因,在targets->Build Setting ->Other Linker Flags中添加-ObjC 添加方法如下 错误2 授权回 ...
- 阶段一:用Handler和Message实现计时效果及其中一些疑问
“阶段一”是指我第一次系统地学习Android开发.这主要是对我的学习过程作个记录. 本来是打算继续做天气预报的优化的,但因为某些原因,我要先把之前做的小应用优化一下.所以今天就插播一下用Handle ...
- React Native知识11-Props(属性)与State(状态)
一:Props(属性) 大多数组件在创建时就可以使用各种参数来进行定制.用于定制的这些参数就称为props(属性).props是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变 通过 ...
- C#使用ADO.NET访问数据库(一)
博主好久没更新博客了,最近有点忙(打麻将0.0..),今天更新一篇C#的,我还是想坚持更新博客,分享一下自己的心得,闲话少说,开始正题~~ ADO.NET概述:ADO.NET的作用在于他是客户端访问服 ...
- 15-static和extern关键字1-对函数的作用
一.extern与函数 如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.ob ...
- [Erlang 0118] Erlang 杂记 V
我在知乎回答问题不多,这个问题: "对你职业生涯帮助最大的习惯是什么?它是如何帮助你的?",我还是主动回答了一下. 做笔记 一开始笔记软件做的不好的时候就发邮件给自己, ...
- 百度广告 高亮 Chrome插件(附源码)
一前言 百度最近是上了舆论头条了,相信中过百度毒的人对百度都反感.百度自己挖了这么多坑,终究还是要自己来填.国内网民使且最频繁的搜过 还是以百度为主,而百度依靠这种市场占有率靠他的广告竞价排名大发横财 ...
- oracle日常——修改用户密码
修改密码时,先进入sqlplus的sql命令状态(键入用户名密码之后),命令如下: alter user cnp2 identified by cnp3; --即将用户cnp2的密码修改为cnp3 格 ...
- 内核控制Meta标签:让360浏览器默认使用极速模式打开网页(转)
为了让网站页面不那么臃肿,也懒的理IE了,同时兼顾更多的国内双核浏览器,在网页页头中添加了下面两行Meta控制标签. 1,网页头部加入 <meta name="renderer&quo ...
- MS SQL SERVER导出表结构到Excel
通过sql语句导出表结构 SELECT 表名 Then D.name Else '' End, 表说明 Then isnull(F.value,'') Else '' End, 字段序号 = A.co ...