摘要:变量用命令声明,不会发生变量提升。报错不报错块级作用域实际上为新增了块级作用域。这表示外层代码块不受内层代码块的影响。以下两行都会报错声明变量的六种方法只有两种声明变量的方法命令和命令。之中,顶层对象的属性与全局变量是等价的。
let 与 cost
1.使用 let 关键字声明变量,与使用 var 关键字声明变量书写方式一致;
{ let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1
上面代码在代码块之中,分别用 let 和 var 声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。
通过一个简单的循环来初步了解使用 let 关键字声明变量 与 传统的 var 关键字声明变量的区别
var a = []; for (var i = 0; i < 10; i++) { a[i] = function() { console.log(i); }; } a[6](); // 10
上面代码中,变量i是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。
var a = []; for (let i = 0; i < 10; i++) { a[i] = function() { console.log(i); }; } a[6](); // 6
而这段代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
2.不存在变量提升
// var 的情况 console.log(foo); // 输出undefined var foo = 2; // let 的情况 console.log(bar); // 报错ReferenceError let bar = 2;
上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。
3.暂时性死区
在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)
if (true) { // TDZ开始 tmp = "abc"; // ReferenceError console.log(tmp); // ReferenceError let tmp; // TDZ结束 console.log(tmp); // undefined tmp = 123; console.log(tmp); // 123 }
上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错
4.不允许重复声明
let不允许在相同作用域内,重复声明同一个变量。
// 报错 function func() { let a = 10; var a = 1; } // 报错 function func() { let a = 10; let a = 1; }
因此,不能在函数内部重新声明参数。
function func(arg) { let arg; } func() // 报错 function func(arg) { { let arg; } } func() // 不报错
5.块级作用域
let实际上为 JavaScript 新增了块级作用域。
function f1() { let n = 5; if (true) { let n = 10; } console.log(n); // 5 }
上面的函数有两个代码块,都声明了变量n,运行后输出 5。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量n,最后输出的值才是 10
6.const
const声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable.
const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值 const的作用域与let命令相同:只在声明所在的块级作用域内有效
if (true) { const MAX = 5; } MAX // Uncaught ReferenceError: MAX is not defined
const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用 const声明的常量,也与let一样不可重复声明。
var message = "Hello!"; let age = 25; // 以下两行都会报错 const message = "Goodbye!"; const age = 30;
ES6 声明变量的六种方法 ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令;还有import命令和class命令(这两与本文关系不大,了解即可)
7.顶层对象的属性
顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。ES5 之中,顶层对象的属性与全局变量是等价的。
window.a = 1; a // 1 a = 2; window.a // 2
上面代码中,顶层对象的属性赋值与全局变量的赋值,是同一件事。
ES6 为了改变这一点,一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性
而在ES6(ECMAScript 6 以下简称 ES6)语法中,就会报错
var a = 1; let b = 1; window.b // undefined
上面代码中,全局变量a由var命令声明,所以它是顶层对象的属性;全局变量b由let命令声明,所以它不是顶层对象的属性,返回undefined。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/102300.html
摘要:当发出一个请求的时候,如果这个请求需要等待,那就会被放入队列中,如果有别的请求发出,并且无需等待则立刻做出处理,之后,再调用该请求的回调。差异相对于浏览器而言是没有对象的也没有浏览器安全级别的限制也不具备只能运行 node初体验 1、node环境 node 是一个服务端JavaScript解析器,node中this指向global,而在浏览器中this指向window 所以unde...
摘要:摘要实践内存初探闲鱼技术匠修我们想使用来统一移动开发并做了一些实践。将内存管理分为新生代和老年代。在标记阶段,所有线程参与并发的完成对回收对象的标记,降低标记阶段耗时。的首帧渲染耗时较高,在版本有明显感受,大概会黑屏秒,版本会好很多。 摘要: Android Flutter实践内存初探 闲鱼技术-匠修我们想使用Flutter来统一移动App开发并做了一些实践。移动设备上的资源有限,通常...
阅读 2590·2021-09-26 10:13
阅读 6010·2021-09-08 10:46
阅读 697·2019-08-30 15:53
阅读 2972·2019-08-29 16:13
阅读 2765·2019-08-26 12:23
阅读 3495·2019-08-26 11:24
阅读 1101·2019-08-23 18:09
阅读 1038·2019-08-23 17:08