ECMAScript 6 学习笔记:变量定义方法
栏目: JavaScript · 发布时间: 6年前
内容简介:let 声明的变量只在 let 命令所在的代码块内有效。如果在 let 命令所在代码块外调用,则会报错。let 命令的特性导致它非常适合用于 for 循环,每次循环的 i 都是不同的变量,但是每一轮循环都会记住上一轮循环的值,而 var 声明的全局变量,每次循环都是同一个变量:使用传统的 var 定义变量的方式,声明的变量会发生变量提升现象,即定义的变量在编译时被提到了代码的头部,具体表现为变量可以在声明之前使用,值为 undefined。而 let 纠正了这种行为,使用 let 声明的变量一定要在声明后使
ES6 声明变量的六种方法
- var 和 function
- let 和 const
- import 和 class
let 命令
基本用法
let 声明的变量只在 let 命令所在的代码块内有效。如果在 let 命令所在代码块外调用,则会报错。
{ let foo = 1; var bar = 2; console.log(foo); // 1 console.log(bar); // 2 } console.log(foo); // ReferenceError: foo is not defined console.log(bar); // 2
let 命令的特性导致它非常适合用于 for 循环,每次循环的 i 都是不同的变量,但是每一轮循环都会记住上一轮循环的值,而 var 声明的全局变量,每次循环都是同一个变量:
// 使用 var 定义变量 var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[1](); // 无论如何都是 10,因为这里的 i 是全局变量 // 使用 let 定义变量 var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[1](); // 输出 1,尽管每次循环的 i 都是重新定义的,但是 for 会记住上一次 i 的值
变量提升
使用传统的 var 定义变量的方式,声明的变量会发生变量提升现象,即定义的变量在编译时被提到了代码的头部,具体表现为变量可以在声明之前使用,值为 undefined。而 let 纠正了这种行为,使用 let 声明的变量一定要在声明后使用,否则会报错。
// 存在变量提升 console.log(foo); // 输出 undefined var foo = 1; // 不存在变量提升 console.log(bar); // 报错 ReferenceError let bar = 1;
暂时性死区
只要块级作用域内存在 let 命令,它所声明的变量就“绑定”这个区域,不再受到外部的影响。ES6 明确规定,如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。这种行为在语法上称为“暂时性死区”。
var foo = 1; { foo = 2; // 报错 ReferenceError let foo; // 由于 let 的存在,区块被绑定,变量无法提升,因此上面会报错 }
重复声明
let 不允许在相同作用域内,重复声明同一个变量
{ let a = 1; let a = 2; // 报错 } { let a = 1; { let a = 2; // 不报错 } }
块级作用域
ES5 只有全局作用域和函数作用域,没有块级作用域,这样可能导致多种问题:
- 内层变量覆盖外层变量
var tmp = 1; function f() { console.log(tmp); if (false) { var tmp = 2; } } f(); // undefined,因为 if 代码块中的变量发生了变量提升,导致 console.log 无法读取外部变量
- 计数循环变量泄露为全局变量,如上文介绍 for 循环时所提到的那样。
ES6 允许块级作用域的任意嵌套,外层作用域无法读取内层作用域的变量,内层作用域可以定义外层作用域的同名变量。
{ {let insane = 'Hello World'} console.log(insane); // 报错,外层作用域无法读取内层作用域的变量 };
函数声明
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于 let,在块级作用域之外不可引用。但是在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于 var 声明的变量。考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。另外,还有一个需要注意的地方。ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。
// 不报错 'use strict'; if (true) { function f() {} } // 没有大括号,报错 'use strict'; if (true) function f() {}
const 命令
const 声明一个只读的常量,一旦声明,常量的值就不能改变,这意味着,const 一旦声明变量,就必须立即初始化,不能留到以后赋值。const 命令的语法特性与 let 命令相同,比如作用域、变量提升规则等。
const PI = 3.1415; PI = 3; // TypeError: Assignment to constant variable.
const 命令保证的是变量指向的内存地址保存的数据不能改动,而对于对象和数组,const 只能保证指向对象和数组的指针不变,因此对于 const 声明的对象和数组是可以使用其内部方法添加数值的,但是无法指向另一个对象或者数组。
const foo = {}; // 为 foo 添加一个属性,可以成功 foo.prop = 123; foo.prop // 123 foo = {123}; // TypeError: "foo" is read-only
如果需要声明一个完全无法改动的对象,应该使用 Object.freeze 方法,将对象和对象的属性全部冻结:
// 使用递归函数将对象和对象的属性全部冻结 var constantize = (obj) => { Object.freeze(obj); Object.keys(obj).forEach((key, i) => { if (typeof obj[key] === 'object') { constantize(obj[key]); } }); };
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 02-GoLang定义变量
- go变量定义
- Golang——变量的声明与定义
- gradle使用技巧(def定义变量 rootProject.ext 添加全局变量)
- 在CoffeeScript中定义私有成员变量
- 在CoffeeScript中定义私有成员变量
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。