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 ...
随机推荐
- arcgis engine 中出现的内存堆栈溢出问题。
两种解决方案: 1.循环加载mxd文档的时候出现的堆栈溢出,解决办法是每次循环结束时清空FeatureLayer,感觉并不好,但是确实可以实现功能. 2.循环调取featureclass的search ...
- ArcGIS Engine开发之属性查询
属性查询即基于空间数据的属性数据的查询,通过用户提交SQL语言中的where语句定义的查询条件,对属性数据进行搜索,从而得到查询结果的操作. 相关的类与接口 与属性查询功能相关的类主要有QureyFi ...
- android 帧动画
首先在res/drawable/name1.xml/定义一组图片集合: <?xml version="1.0" encoding="utf-8"?> ...
- 网络安全——Base64编码、MD5、SHA1-SHA512、HMAC(SHA1-SHA512)哈希
据说今天520是个好日子,为什么我想起的是502.500.404这些?还好服务器没事! 一.Base64编码 Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之 ...
- MySQL安装与基本配置
一.简介 SQL语言 DDL:表.视图.索引.触发器操作等.CREATE/ALTER/DROP语句 DML:数据操作.SELECT/INSERT/UPDATE/DELETE DCL:权限设置.GRAN ...
- 最新官方WIN10系统32位,64位系统ghost版下载
系统来自:系统妈 随着Windows 10Build 10074 Insider Preview版发布,有理由相信,Win10离最终RTM阶段已经不远了.看来稍早前传闻的合作伙伴透露微软将在7月底正式 ...
- get方式和set方式提交时乱码
request.setChracterEncoding("utf-8");只对form表单的post提交方式有效. 当使用get提交的时候:
- [No0000AD]7z源码完全移植至Visual Studio 2015
今天在上次的基础上(原文地址:[No0000AB]用Visual Studio 2015在 WIN10 64bit 上编译7-zip (32 bit)),将7Z的源码完全移植到了vs2015开发环境下 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- 索引超出了数组界限(Microsoft.SqlServer.Smo)
SSMS连接远程SQL Server服务器是很方便的. 昨天我用SQL Server 2008 SSMS连接SQL Server 2012竟然报错,如下图: 在网上搜了,参考这个参考那个,太啰嗦了,确 ...