资讯专栏INFORMATION COLUMN

ES6简记

renweihub / 3471人阅读

摘要:圆括号问题可以使用圆括号的情况只有一种赋值语句的非模式部分,可以使用圆括号。正确正确正确上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句其次它们的圆括号都不属于模式的一部分。

let 和 const 命令
1.let

概念:

暂时性死区(TDZ)

在作用域内,let变量已经存在;
并绑定该作用域:不受外界影响,外界也不可获取
let作用域以代码块划分,var作用域则只有全局和函数

在let声明之前,不可获取;(也就是TDZ)

在let声明之后,才可获取。

let变量不可重复声明

let不允许在相同作用域内,重复声明同一个变量。

tip:

TDZ也解释了为什么let不存在变量提升。

ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。

2.块级作用域

ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景,如:

内层变量可能会覆盖外层变量。

用来计数的循环变量泄露为全局变量。

ES6 的块级作用域(let实际上为 JavaScript 新增了块级作用域),作用:

外层作用域无法读取内层作用域的变量。

内层作用域可以定义外层作用域的同名变量。

使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。

根据ES6 在附录 B里的规定,在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量。

3.const 命令

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。

冻结对象:

const foo = Object.freeze({});

彻底冻结对象的函数:

var constantize = (obj) => {
       Object.freeze(obj);
    Object.keys(obj).forEach((key, i) => 
        if ( typeof obj[key] === "object" ) {
            constantize( obj[key] );
        }
    });
};

ES6 声明变量的六种方法
ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。

4.顶层对象的属性

从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1

let b = 1;
window.b // undefined
变量的解构赋值
1.数组的解构赋值

基本用法:

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [x, , y] = [1, 2, 3];
x // 1
y // 3

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ["a"];
x // "a"
y // undefined
z // []

默认值

let [foo = true] = [];
foo // true

let [x, y = "b"] = ["a"]; // x="a", y="b"
let [x, y = "b"] = ["a", undefined]; // x="a", y="b"

注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。

let [x = 1] = [undefined];
x // 1

let [x = 1] = [null];
x // null

默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

let [x = 1, y = x] = [];     // x=1; y=1
let [x = 1, y = x] = [2];    // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = [];     // ReferenceError: y is not defined

上面最后一个表达式之所以会报错,是因为x用y做默认值时,y还没有声明。

2.对象的解构赋值

命名与键名相同则简写:

let { bar, foz } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // undefined

命名与键名不同:

let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"

嵌套:

let obj = {
  p: [
    "Hello",
    { y: "World" }
  ]
};

let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
let obj = {};
let arr = [];

({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });

obj // {prop:123}
arr // [true]

默认值:

var {x = 3} = {};
x // 3

var {x, y = 5} = {x: 1};
x // 1
y // 5

var {x: y = 3} = {};
y // 3

var {x: y = 3} = {x: 5};
y // 5

var { message: msg = "Something went wrong" } = {};
msg // "Something went wrong"

如果要将一个已经声明的变量用于解构赋值,必须非常小心:

// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

// 正确的写法
let x;
({x} = {x: 1});

由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
3.字符串的解构赋值

字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

const [a, b, c, d, e] = "hello";
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

let {length : len} = "hello";
len // 5
4.数值和布尔值的解构赋值

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true
5.函数参数的解构赋值
function move({x = 0, y = 0} = {}) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]

上面代码中,函数move的参数是一个对象,通过对这个对象进行解构,得到变量x和y的值。如果解构失败,x和y等于默认值。

注意,下面的写法会得到不一样的结果。
上面代码是为函数move的参数指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果。

function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
6.圆括号问题

可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。

[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确

上面三行语句都可以正确执行,因为首先它们都是赋值语句,而不是声明语句;其次它们的圆括号都不属于模式的一部分。
第一行语句中,模式是取数组的第一个成员,跟圆括号无关;
第二行语句中,模式是p,而不是d;
第三行语句与第一行语句的性质一致。

7.用途

(1)交换变量的值
(2)从函数返回多个值
(3)函数参数的定义
(4)提取 JSON 数据
(5)函数参数的默认值
(6)遍历 Map 结构
(7)输入模块的指定方法

数组的拓展
1.扩展运算符(...)

用法简单,写ES6的时候留意下是否可以用之与简化代码即可,
注意点:
解构赋值的时候必须放在末尾,否则报错(Rest element must be last element)。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93743.html

相关文章

  • JavaScript简记(一)

    摘要:基础属性操作及注意事项待更新。。解决方案可以用视觉方案处理,比如切换显示隐藏。设置浮动时,采用在标准浏览器是支持的,在某些浏览器是不支持的。第三种判断形式条件当条件成立执行条件当条件不成立,条件成立,则执行。适用于,当某件事成立执行。 js基础--属性操作及注意事项 待更新。。 关于属性操作注意事项 1、所有相对路径都别拿来比较!!!(绝对路径可以,入img src=https://s...

    rozbo 评论0 收藏0
  • HDFS架构一图简记

    摘要:会实时从上读取信息,进行重演,保持与的数据同步。如果挂掉了,会监控到,向集群发送心跳报告时会将这一消息报告上去,集群会进行选举,被选举到的所在节点的进程收到通知,这个会切换的状态为。 showImg(https://segmentfault.com/img/bVbqOJn?w=1280&h=720); 读写:客户端通过命名空间发请求,可以无感知的找到active NN,active N...

    姘搁『 评论0 收藏0
  • YARN架构一图简记

    摘要:启动时会向的路径下写入文件,写入成功的则为,否则为。根据上下文以及从收集到的状态信息分配资源并调度,启动一个用来运行。负责启动,监控所在节点的资源使用情况,并通过心跳机制报告给。 showImg(https://segmentfault.com/img/bVbqOVb?w=1280&h=720); HA:RM启动时会向zk的/mrstore路径下写入lock文件,写入成功的则为acti...

    rubyshen 评论0 收藏0

发表评论

0条评论

renweihub

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<