一、let和const命名
let命令是用来申明变量的。用法和var类似,不同的是let作用域只在{}之间,var会进行申明置顶,全局有效。
for(var i=0;i<10;i++){
//do something
}
console.log(i);//10
//let
for(let j=0;j<10;j++){
//do something
}
console.log(j);//Uncaught ReferenceError: j is not defined
var进行变量提升后的结果见下
var i;
for(i=0;i<10;i++){
//do something
}
console.log(i);//10
let的使用有几点需要注意
- 同一作用域不允许重复申明
- for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
const用来定义常量的,重复赋值的会报错,先定义,再使用
二、数据的结构赋值
1、数组
let [a,b,c] = [1,2,3];//完全解构 ok
let [e,f,g] = [4,5];//不完全解构 ok
let [h, ,j]= [5,6,7];//不完全解构 h=5,j=7
let [l,m] = [7,,9];//不完全解构 l=7, m=undefind
let l,m = [7,,9]; //不完全解构 l=undefind,m=[7, ,9] 避免
解构是可以指定默认值的,例:let [l,m=8] = [7,,9]
2、对象
ES6还可以进行对象的解构,数组的解构按顺序,对象的解构按键
let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
值得注意的是let { bar, foo }只是一种简写,补全后是
let { bar:bar, foo:foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
bar:bar 第一个是匹配模式,第二个才是赋值的
let { bar:bar1, foo:foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar1 // "bbb"
bar // Uncaught ReferenceError: bar is not defined
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 a = 1;
let b = 2;
[a,b] = [b,a];
既方便又简捷
从函数返回多个值
// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
函数只能返回一个参数,通过这个可以进行多个参数的接收
提取 JSON 数据
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);// 42, "OK", [867, 5309]
上面代码可以快速提取 JSON 数据的值,尤其有用。
函数参数的默认值
jQuery.ajax = function (url, {
async = true,
beforeSend = function () {},
cache = true,
complete = function () {},
crossDomain = false,
global = true,
// ... more config
} = {}) {
// ... do stuff
};
指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || 'default foo';
这样的语句。
输入模块的指定方法
加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
const { SourceMapConsumer, SourceNode } = require("source-map");
3、模板字符串
s6模板字符简直是开发者的福音啊,解决了ES5在字符串功能上的痛点。
第一个用途,基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定。
//ES5
var name = 'lux'
console.log('hello' + name)
//es6
const name = 'lux'
console.log(`hello ${name}`) //hello lux
第二个用途,在ES5时我们通过反斜杠()来做多行字符串或者字符串一行行拼接。ES6反引号(``)直接搞定。
// ES5
var msg = "Hi \
man!
"
// ES6
const template = `
hello world
`
4、Spread Operator 展开运算符
ES6中另外一个好玩的特性就是Spread Operator 也是三个点儿...接下来就展示一下它的用途。
组装对象或者数组
//数组
const color = ['red', 'yellow']
const colorful = [...color, 'green', 'pink']
console.log(colorful) //[red, yellow, green, pink]
//对象
const alp = { fist: 'a', second: 'b'}
const alphabets = { ...alp, third: 'c' }
console.log(alphabets) //{ "fist": "a", "second": "b", "third": "c"
}
5、import和export
import导入模块、export导出模块
//全部导入
import people from './example'
//有一种特殊情况,即允许你将整个模块当作单一对象进行导入
//该模块的所有导出都会作为对象的属性存在
import * as example from "./example.js"
console.log(example.name)
console.log(example.age)
console.log(example.getName())
//导入部分
import {name, age} from './example'
// 导出默认, 有且只有一个默认
export default App
// 部分导出
export class App extend Component {};
以前有人问我,导入的时候有没有大括号的区别是什么。下面是我在工作中的总结:
1.当用export default people导出时,就用 import people 导入(不带大括号)
2.一个文件里,有且只能有一个export default。但可以有多个export。
3.当用export name 时,就用import { name }导入(记得带上大括号)
4.当一个文件里,既有一个export default people, 又有多个export name 或者 export age时,导入就用 import people, { name, age }
5.当一个文件里出现n多个 export 导出很多模块,导入时除了一个一个导入,也可以用import * as example
6、类和继承
Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
class Point {
}
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}
上面代码中,constructor方法和toString方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
参考文献
http://es6.ruanyifeng.com/#docs/intro