ecmascript7.0知识点(技术共享ECMAScript)
ecmascript7.0知识点(技术共享ECMAScript)(2)export命令// var 的情况count = count 1;① 不存在变量提升var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined。纠正这种现象,const和let命令改变了语法行为,它所声明的常量和变量一定要在声明后使用,否则报错。
(1)const 和 let命令
ES6 新增了const和let命令,分别表示常量和变量。不同于var的函数作用域,const和let 都是块级作用域。
const DELAY = 1000;
let count = 0;
count = count 1;
① 不存在变量提升
var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined。纠正这种现象,const和let命令改变了语法行为,它所声明的常量和变量一定要在声明后使用,否则报错。
// var 的情况
(2)export命令
export命令对外部输出变量。
// profile.as
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName lastName year};
export命令除了输出变量,还可以输出函数或类(class)。export输出的变量就是本来的名字,但是可以使用as关键字重命名。
export function multiply(x y) {
return x * y;
};
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1
v2 as streamV2
v2 as streamLatestVersion
};
特别注意:export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
// 报错
export 1;
// 报错
var m = 1;
export m;
// 正确写法
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
4.ES6 对象和数组(1)解构赋值
解构赋值让我们从 对象或 数组里取部分数据存为变量。
① 数组的解构赋值
可以从数组中提取值,按照对应位置,对变量赋值。本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
let [a b c] = [1 2 3];
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 // []
如果等号的右边不是数组(或者严格地说,不是可遍历的结构,参见《Iterator》一章),那么将会报错。
// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
对于 Set 结构,也可以使用数组的解构赋值。
let [x y z] = new Set(['a' 'b' 'c']);
x // "a"
默认值
解构赋值允许指定默认值。 注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。
let [foo = true] = [];
foo // true
let [x y = 'b'] = ['a']; // x='a' y='b'
let [x y = 'b'] = ['a' undefined]; // x='a' y='b'
如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined,所以y取值b。
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。因为x能取到值,所以函数f根本不会执行。
function f() {
console.log('aaa');
}
let [x = f()] = [1];
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
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
② 对象的解构赋值
对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let { bar foo } = { foo: "aaa" bar: "bbb" };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: "aaa" bar: "bbb" };
baz // undefined
python
如果变量名与属性名不一致,必须写成下面这样。
let { foo: baz } = { foo: 'aaa' bar: 'bbb' };
baz // "aaa"
let obj = { first: 'hello' last: 'world' };
let { first: f last: l } = obj;
f // 'hello'
l // 'world'
与数组一样,解构也可以用于嵌套结构的对象。
let obj = {
p: [
'Hello'
{ y: 'World' }
]};
let { p: [x { y }] } = obj;
x // "Hello"
y // "World"
注意,这时p是模式,不是变量,因此不会被赋值。如果p也要作为变量赋值,可以写成下面这样。
let obj = {
p: [
'Hello'
{ y: 'World' }
]};
let { p p: [x { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello" {y: "World"}]
默认值
对象的解构也可以指定默认值。
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"
默认值生效的条件是,对象的属性值严格等于undefined。如果x属性等于null,就不严格相等于undefined,导致默认值不会生效。
var {x = 3} = {x: undefined};
x // 3
var {x = 3} = {x: null};
x // null
如果要将一个已经声明的变量用于解构赋值,必须非常小心。
// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error
// 正确的写法
let x;
({x} = {x: 1});
上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
({} = [true false]);
({} = 'abc');
({} = []);
上面的表达式虽然毫无意义,但是语法是合法的,可以执行。
由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
let arr = [1 2 3];
let {0 : first [arr.length - 1] : last} = arr;
first // 1
last // 3
(2)对象字面量改进
对象字面量是两个大括号{},ES6中对对象字面量增加了几个实用的新语法,大大增加了它的易用性。 1)可以在对象字面量里面定义原型 2)定义方法可以不用function关键字 3)直接调用父类方法
// ES5对象字面量
var type = 'rock';
var heat = '50%';
var music = {
type: type
heat: heat
};
console.log(music); // Object {type: "rock" heat: "50%"}
// ES6对象字面量
var type = 'rock';
var heat = '50%';
var music = {
type
heat
};
console.log(music); // Object {type: "rock" heat: "50%"}
这是解构的反向操作,用于重新组织一个 Object 。
const name = 'duoduo';
const age = 8;
const user = { name age }; // { name: 'duoduo' age: 8 }
定义对象方法时,还可以省去 function 关键字。
//通过对象字面量创建对象
var human = {
breathe() {
console.log('breathing...');
} // 等同于 breathe: function() {}
};
var worker = {
__proto__: human //设置此对象的原型为human 相当于继承human
company: 'freelancer'
work() {
console.log('working...');
}
};
human.breathe();//输出 ‘breathing...’
//调用继承来的breathe方法
worker.breathe();//输出 ‘breathing...’
(3)Spread Operator
Spread Operator 即 3 个点 ...,有几种不同的使用方法。 可用于组装数组。
const todos = ['Learn dva'];
[...todos 'Learn antd']; // ['Learn dva' 'Learn antd']
也可用于获取数组的部分项。
const arr = ['a' 'b' 'c'];
const [first ...rest] = arr;
rest; // ['b' 'c']
// With ignore
const [first ...rest] = arr;
rest; // ['c']
还可收集函数参数为数组。
function directions(first ...rest) {
console.log(rest);
}
directions('a' 'b' 'c'); // ['b' 'c'];
代替 apply。
function foo(x y z) {}
const args = [1 2 3];
// 下面两句效果相同
foo.apply(null args);
foo(...args);
对于 Object 而言,用于组合成新的 Object 。(ES2017 stage-2 proposal)
const foo = {
a: 1
b: 2
};
const bar = {
b: 3
c: 2
};
const d = 4;
const ret = { ...foo ...bar d }; // { a:1 b:3 c:2 d:4 }
此外,在 JSX 中 Spread Operator 还可用于扩展 props。
const attrs = {
href: 'http://example.org'
target: '_blank'
};
<a {...attrs}>Hello</a>