ES6--变量的声明及解构赋值
ES6的目标是使得JavaScript语言能够用来编写大型的复杂的应用程序。成为企业级开发语言;该标准已于2015年6月17日正式公布。
可是真正的普及我觉得还得须要一段时间。然而这并非理由让我们不去了解ES6。更重要的一点是,Google公司的V8引擎已经部署了ES6部分特性,对于NodeJS的开发人员来说应该熟练掌握。
在浏览器没有全面支持的情况下,Google公司推出了Traceur转码器(https://github.com/google/traceur-compiler),可将ES6编译为ES5代码。以及如今市面比較流行的Babel转码器(https://babeljs.io/)。其自带一个babel-node命令。提供支持ES6的REPL环境。
$ npm install --global babel
$ babel-node
$ babel-node es6.js
ES6扩充了块级作用域。对字符串、数值、数组、对象、函数等都做了不同程度的扩展;引进了变量解构赋值、Set和Map数据结构、Iterator和for…of循环、Generator函数、Promise对象、Class和Module使得其更加灵活。
在这里,展望一下ES7,在ES7草案中最让人眼前一亮的当属Object.observe()和async函数,这意味在不久的将来。我们将不依赖不论什么框架去实现双向数据绑定和简单易用的异步编程。
一、let、const和块级作用域
了解JavaScript的人提及到它,大家都会想到其不存在块级作用域。而是函数级作用域。
从而导致了诸如“内层变量可能会覆盖外层变量”、“用来计数的循环变量泄露为全局变量”、“循环绑定事件”等问题。
在ES6中。引入了let和const使块级作用域变成现实,马上运行匿名函数(IIFE)变得可替代。
let命令
let与var的异同点比較
内容点 | let | var |
---|---|---|
定义变量 | YES | YES |
可被释放 | YES | YES |
可被提升 | YES | |
反复定义检查 | YES | |
可被用于块级作用域 | YES |
(1)let不会发生“变量提升”现象。
(2)不同意在相同作用域反复声明一个变量;
(3)let的作用域是块。而var的作用域是函数。函数本身的作用域在其所在的块级作用域之内;
演示样例:let块级作用域
{
let a = 1;
var b = 1;
}
a; // Uncaught ReferenceError: a is not defined(…)
b; // 1
演示样例:let块级作用域
for(var i = 0; i < 10; i++){}
i; // 10
for(let j = 0; j < 10; j++){}
j; // Uncaught ReferenceError: j is not defined(…)
演示样例:let不会发生“变量提升”现象
function test(){
console.log(a);
console.log(b);
var a = 1;
let b = 1;
}
test(); // a:undefined;b:Uncaught ReferenceError: b is not defined(…)
这意味着typeof不再是一个百分百安全的操作!!
!
演示样例:typeof安全性
typeof a; // undefined
typeof b; // b:Uncaught ReferenceError: b is not defined(…)
let b;
总之,在代码块内使用let命令之前。该变量是不可用的。在语法上被称为“临时性死区”。
ES6规定临时性死区和不存在变量提升,主要是为了降低运行时错误,防止在变量前就使用这个变量。从而导致意料之外的行为。
演示样例:不同意反复声明
function test(){
let a = 10;
var a = 1;
return a;
}
test(); // Uncaught SyntaxError: Identifier 'a' has already been declared
function f(){
let a = 1;
{
// var a = 2; // 会报错
// let a = 2; // 不会报错
}
}
演示样例:函数本身的作用域在其所在的块级作用域之内
function f() {
console.log('out');
}
(function() {
if(false){
function f() {
console.log('in');
}
}
f();
}()); //ES5中:in;ES6中:out!
演示样例:循环绑定事件
<button>A</button>
<button>B</button>
<button>C</button>
<button>D</button>
<div id="output"></div>
var buttons = document.querySelectorAll("button"),
output = document.querySelector("#output");
方式一:(常规方式)buttons[i].innerHTML 报错
for(var i = 0, len = buttons.length; i < len; i++){
buttons[i].addEventListener("click", function(event){
output.innerHTML = buttons[i].innerHTML;
});
}
方式二:forEach封装函数作用域
var buttonsAry = Array.prototype.slice.apply(buttons);
buttonsAry.forEach(function(currentBtn, index, ary){
currentBtn.addEventListener("click", function(event){
output.innerHTML = currentBtn.innerHTML;
});
});
方式三:(let会计作用域)正常展示(为循环体的每一次运行都产生一个作用域)
for(let i = 0, len = buttons.length; i < len; i++){
buttons[i].addEventListener("click", function(event){
output.innerHTML = buttons[i].innerHTML;
});
}
方式四:for…of迭代
for(let btn of buttons){
btn.addEventListener("click", function(event){
output.innerHTML = btn.innerHTML;
});
}
const命令
const用来声明常量。一旦声明,其值就不能改变。这意味着,const一旦声明常量。就必须马上初始化。const同let命令相同仅仅在当前块级作用域中有效,存在“临时性死区”。
ECMAScript在对变量的引用进行读取时,会从该变量相应的内存地址所指向的内存空间中读取内容,而当用户改变变量的值时,引擎会又一次从内存中分配一个新的内存空间以存储新的值,并将新的内容地址与变量进行绑定。const的原理便是在变量名与内存地址之间建立不可变的绑定,当后面的程序尝试申请的内存空间时。引擎便会抛出错误。
演示样例:常量
const PI = 3.14;
PI = 3.1415; // caught TypeError: Assignment to constant variable.(…)
对于复合型的变量,其指向数据的存储地址。const命令仅仅是保证变量名指向的地址不变,并不保证该地址的数据不变。
演示样例:跨模块常量
/* constants.js 模块 */
export const PI = 3.14;
export const AUTHOR = "LIGANG";
/* a.js 模块 */
import * as constants from "./constants";
console.log(constants.PI, constants.AUTHOR);
/* b.js 模块 */
import {PI, AUTHOR} from "./constants";
console.log(PI, AUTHOR);
变量声明
ES5中声明变量仅仅有两种方法:var
和function
。
ES6中声明变量的方式:var
、function
、let
、const
、import
和class
命令
全局对象的属性
全局对象是最顶层的对象,在浏览器环境指的是window对象。在Node.js指的是global对象。在JavaScript语言中,全部全局变量都是全局对象的属性。
ES6规定,var命令和function命令声明的全局变量,属于全局对象的属性。let命令、const命令、class命令声明的全局变量。不属于全局对象的属性。
var a = 1;
let b = 1;
console.log(window.a); // 1
console.log(window.b); // undefined
更佳体验
在ES6中。let的设计初衷便是为了取代var。
这意味着,TC-39希望在ES6之后。开发人员尽可能甚至彻底不再使用var来定义变量。从project化角度,我们应在ES6中遵循下面三条原则:
(1)使用const来定义值的存储容器(常量);
(2)仅仅用在值容器明白地被确定将会被改变时才使用let来定义(变量);
(3)不再使用var。
二、变量的解构赋值
ES6同意依照一定模式。从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。仅仅要某种数据结构具有Iterator接口。都能够进行解构。
解构的规则是,仅仅要等号右边的值不是对象,就先将其转化为对象。
数组的解构赋值
Syntax: [arg1, arg2] = [value1, value2]
Syntax: [arg1, , arg3] = [value1, value2, value3]
Syntax: [arg1, arg2, ...resetArgs] = [value1, value2, value3, value4]
演示样例:数组解构
var [a, b, c] = [1, 2, 3];
let [foo, [[bar], baz]] = [1 [[2], 3]];
注意:下述几种情况会报错,由于其转为对象不具备Iterator接口。
let [foo] = 1/false/NaN/undefined/null/{};
对象的解构赋值
Syntax: {arg1, arg2} = {arg1: value1, arg2: value2}
演示样例:对象解构
var {foo, bar} = {foo: "aaa", bar: "bbb"};
对象的解构赋值的内部机制,是先找到同名的内部属性,然后再赋值给对象的变量。
真正被赋值的是后者,而不是前者。
var {foo: baz} = {foo: "aaa"};
baz; // "aaa"
foo; // error: foo is not defined
字符串的解构赋值
演示样例:字符串解构
var [a, b, c, d, e] = 'hello';
a; // 'h'
e; // 'o'
函数參数的解构赋值
function add([x, y]){
return x + y;
}
add([1, 2]);
默认值
var {x, y = 5} = {x: 1};
x; // 1
y; // 5
注意: ES6内部使用严格相等“===”推断一个位置是否有值。所以,不严格等于undefined,默认值是不会生效的。
var {x = 3} = {x: undefined};
x; // 3
var {x = 3} = {x: null};
x; // null
用途
(1)交换变量的值:
[x, y] = [y, x]
(2)从函数中返回多个值:
function test(){
return ["ligang", 25];
}
var [name, age] = test();
(3)函数參数的定义:
function f({x, y, z}) {}
f([1, 2, 3]); // 有序
f({x:1, y:2, z:3}); // 无序
(4)函数參数的默认值:避免了使用“||”操作
function test({a = 1, b = 2}){}
(5)提取JSON数据
var jsonData = {
name: 'ligang',
age: 25,
data: [100, 99]
};
let {id, status, data} = jsonData;
(6)遍历Map数据结构:
for(let [key, value] of map){}
(7)输入模块的指定方法:
载入模块时,往往须要指定输入哪些方法。解构赋值使得输入语句很清晰。
const {testMethod1, testMethod2} = require("constants");
(8)深层匹配:
有时我们须要获取某深层对象中属性,ES6之前我们仅仅能一层层迭代获取,在ES6中能够通过模式匹配进行获取。
演示样例:Object in Object
var obj = {
a: 1,
b: {
c: 3
}
};
// 后去属性a和c的值
let {a, b:{c}} = obj;
console.log(a); // 1
console.log(b); // Uncaught ReferenceError: b is not defined
console.log(c); // 3
// 能够给c指定别名
let {a, b:{c: t}} = obj;
console.log(a); // 1
console.log(b); // Uncaught ReferenceError: b is not defined
console.log(c); // undefined
console.log(t); // 3
演示样例:Array in Object
let {a, b: [x, y]} = {a: 1, b: [2, 3]};
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
演示样例:Object in Array
let [a, {b, c}] = [1, {b: 2, c: 3}];
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
演示样例:Array in Array
let [a, [b, c]] = [1, [2, 3]];
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
注意
- 解构不成功。变量的值为undefined;
- 解构仅仅能用于数组或对象,原始类型能够转为相应的对象,可是对undefined或null进行解构,就会报错;
var [foo] = undefined; // TypeError
var [foo] = null; // TypeError
- 仅仅要有可能导致解构的歧义,就不得使用圆括号。
ES6--变量的声明及解构赋值的更多相关文章
- JavaScript学习笔记(八)——变量的作用域与解构赋值
在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...
- es6(二):解构赋值
ES中允许按照一定格式从数组,对象值提取值,对变量进行赋值,这就是解构(Destructuring) let [a,b,c]=[1,10,100] console.log(a,b,c)//1 10 1 ...
- ES6 (一)变量声明方法 & 解构赋值
就是最新的JavaScript 原来的是var,要求不严格,不能限制修改,函数级 es6要求严格 1.防止重复声明 let 变量=var const 常量 2.控制修改 const常量不能修 ...
- 001-es6变量声明、解构赋值、解构赋值主要用途
一.基本语法 1.1.声明变量的六种方法 参看地址:http://es6.ruanyifeng.com/#docs/let let:局部变量,块级作用域,声明前使用报错 var:全局变量,声明前使用 ...
- ES6笔记(3)-- 解构赋值
系列文章 -- ES6笔记系列 解构赋值,即对某种结构进行解析,然后将解析出来的值赋值给相关的变量,常见的有数组.对象.字符串的解构赋值等 一.数组的解构赋值 function ids() { ret ...
- es6基础系列三:解构赋值
解构就是ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值(只能用于数组,对象或迭代器).如果解构不成功,则等于undefined,但不能赋值为undefined和null,因为undefi ...
- 【系统学习ES6】第二节:解构赋值
[系统学习ES6] 本专题旨在对ES6的常用技术点进行系统性梳理,帮助大家对其有更好的掌握,希望大家有所收获. ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构.解构是一种打 ...
- 深入理解ES6(二)(解构赋值)
变量的解构赋值 (1) 数组的解构赋值 1.基本用法 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring ). 只要等号两边的模式相同,左边的变量 ...
- ES6新特性:利用解构赋值 (destructuring assignment), 简化代码
本文的Demo的运行环境为nodeJS, 参考:让nodeJS支持ES6的词法----babel的安装和使用 : 解构赋值是一种表达式, 利用这种新语法, 可以直接从数组或者对象中快速提取值 赋值给不 ...
随机推荐
- C++ 第十一课 标准c内存函数
calloc() 分配一个二维储存空间 free() 释放已分配空间 malloc() 分配空间 realloc() 改变已分配空间的大小 calloc 语法: #include <st ...
- QtWebkit包含的类简介
前言 WebKit从Qt 4.4开始被作为一个Module被集成到Qt中.简单的说,Qt webkit就是Qt对Apple公司webkit的支持而开发的库,主要包括以下几个类: QWebDatabas ...
- stingray前端架构总体设计及运行过程
SPA 单页应用程序,在一个页面内用ajax技术实现所有的功能的web程序,我们称之为单页应用,明显的特点就是第一次加载之后地址栏非参数部分不再发生变化.大家观察会发现 WIP系统就是一个SPA.我们 ...
- Java Netty (1)
Netty是由JBOSS提供的一个java开源框架,本质上也是NIO,是对NIO的封装,比NIO更加高级,功能更加强大.可以说发展的路线是IO->NIO->Netty. ServerBoo ...
- Eclipse Java注释模板设置详解以及版权声明
网上的Eclipse注释模板,在这里稍稍整理一些比较常用的. 编辑注释模板的方法:Window->Preference->Java->Code Style->Code Temp ...
- MongoDB副本集配置系列三:副本集的认证方式
1:副本集配置参考这篇博客: http://www.cnblogs.com/xiaoit/p/4478951.html 2:副本集的认证 假设有两台机器已经配置好了副本集(副本集罪一般最少3台机器,这 ...
- JSP九大内置对象辨析
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6043096.html JSP中一共预先定义了9个这样的对象,分别为:request.response.sess ...
- 使用c语言调用python小结
近期在做一个漏洞展示平台,攻击实现部分使用python实现.c语言实现部分使用libcli库做一个类似telnet的东东,回调函数run的时候调用python模块. 针对c调用python,做个了小d ...
- javascript用正則表達式检測username的合法性
在用户登录.用户注冊时经常须要对username如邮箱.手机号进行校验,一般经常使用表达式. 以下整理对邮箱和手机号的表达式校验: function checkUser(){ var userName ...
- 一个简单的ExtJS搜索建议框
封装的是一个Ext4.2的组件,继承并兼容于Ext的ComboBox. 实现原理非常easy,在 combo 中监听 keyup 事件就可以. 搜索建议的Combo.基本上全然兼容, 使用方式与Com ...