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
Let & Const的更多相关文章
- openssl 1.1.1 reference
openssl 1.1.1 include/openssl aes.h: # define HEADER_AES_H aes.h: # define AES_ENCRYPT 1 aes.h: # de ...
- const,static,extern 简介
const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...
- C++中的const
一,C++中const的基本知识 1.C++中const的基本概念 1.const是定义常量的关键字,表示只读,不可以修改. 2.const在定义常量的时候必须要初始化,否则报错,因为常量无法修改,只 ...
- const extern static 终极指南
const extern static 终极指南 不管是从事哪种语言的开发工作,const extern static 这三个关键字的用法和原理都是我们必须明白的.本文将对此做出非常详细的讲解. co ...
- const let,console.log('a',a)跟console.log('a'+a)的区别
const 创建一个只读的常量 let块级作用域 const let重复赋值都会报错 console.log('a',a) a console.log('a'+a) a2 逗号的值会有空格:用加号的值 ...
- es6之let和const
在javascript中,我们都知道使用var来声明变量.javascript是函数级作用域,函数内可以访问函数外的变量,函数外不能访问函数内的变量. 函数级作用域会导致一些问题就是某些代码块内的变量 ...
- construction const parameter问题 构造函数const引用参数问题
工程在window下编译没有任何问题, 但是在linux(CentOS6)下编译就老是报错 C++ 编译器已升级到最新版 6.1.0 错误如下: In file included /bits/stl_ ...
- Error:const char* 类型的实参和LPCWSTR类型的形参不兼容的解决方法。
在C++的Windows 应用程序中经常碰到这种情况. 解决方法: 加入如下转换函数: LPCWSTR stringToLPCWSTR(std::string orig) { size_t origs ...
- C#基础知识七之const和readonly关键字
前言 不知道大家对const和readonly关键字两者的区别了解多少,如果你也不是很清楚的话,那就一起来探讨吧!探讨之前我们先来了解静态常量和动态常量. 静态常量 所谓静态常量就是在编译期间会对变量 ...
- const 与 readonly知多少
原文地址: http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.html 尽管你写了很多年的C#的代码,但是可能当别人问到你cons ...
随机推荐
- 探索RegisterAllAreas
在MVC中注册Area时,我们一般会在相应的区域下定义一个继承与AreaRegistration的类,代码如下: public class AdminAreaRegistration : AreaRe ...
- asp.net获取服务端和客户端信息
asp.net获取服务端和客户端信息 获取服务器名:Page.Server.ManchineName获取用户信息:Page.User 获取客户端电脑名:Page.Request.UserHostNam ...
- mysql_建立索引的优缺点 #转自Starzm#
建立索引的优缺点: 为什么要创建索引呢? 这是因为,创建索引可以大大提高系统的性能. 第一.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性. 第二.可以大大加 ...
- Sublime Text 3
Sublime Text 3 插件安装 安装 Package Control 按 Ctrl+` 或者,菜单 View > Show Console 打开命令窗口 import urllib.re ...
- shell parameter expansitions
type testtype -a test math calculate:echo $((1+2*3)) parameter expansition:bash-4 introduced feature ...
- monkeyrunner之测试结果判断(八)
monkeyrunner的功能脚本编写完成之后,我们就需要对结果进行判断,判断结果是否为我们预期的结果值.下面我们主要讲述2种方式判断结果. 方式一.monkeyrunner截图对比 这是monkey ...
- Chrome插件: 网站收藏
在工作中我们会收藏很多网址.以前一直都是用的chrome里面的收藏夹.后面觉得一点都不方便.看一下Chrome插件开发挺容易入手的所以自己写了一个Chrome插件. 基于:Angularjs + ...
- hdu1521 排列组合(指数型母函数)
题意: 有n种物品,并且知道每种物品的数量ki.要求从中选出m件物品的排数. (全题文末) 知识点: 普通母函数 指数型母函数:(用来求解多重集的排列问题) n个元素,其中a1,a2, ...
- UDP
我们通过以下代码来连了解以下UPD 首先我们先创建Server类 package cn.a.qwe; import java.net.DatagramPacket; import java.net.D ...
- Struts2 Ajax校验
Ajax(Asynchronous javascript and xml):异步刷新技术 技术组成: CSS + xml +JavaScript +DOM Ajax核心对象: XMLHttpRequ ...