Ecmascript 6
- ECMAScript 6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了。
- Ecmascript 是 JavaScript 语言的标注规范
- JavaScript 是 Ecmascript 规范的具体实现
- 具体实现取决于各大浏览器厂商的支持进度
- Ecmascript 6 也被称作 Ecmascript 2015
- 各大浏览器厂商对于最新的 Ecmascript 6 标准支持可以参照:
- 对于不支持 ES6 的环境,可以使用一些编译转码工具做转换处理再使用
- 例如 babel
let 和 const
- let 类似于 var,也是用来定义变量的
- 通过 let 定义的变量是块级作用域,只在当前代码块有效
- const 也类似于 var,用来定义常量
- 通过 const 定义的常量,定义的时候必须初始化
- const 定义的变量一旦定义,不能修改
- let 和 const 都没有作用域提升
- let 和 const 在一个块级作用域中都不能重复定义
解构赋值
数组解构:
let [a, b, c] = [123, 456, 789]
console.log(a, b, c) //123 456 789
方法:
// 将一个伪数组转为一个真正的数
Array.from()
// Array.of方法用于将一组值,转换为数组
Array.of()
// 查找某个元素
Array.find()
// 查找某个元素的索引下标
Array.findIndex()
对象解构:
let { name, age } = { name: 'Jack', age: 18 }
console.log(name, age)// Jack 18
函数参数解构:
function f (p1, { p2 = 'aa', p3 = 'bb' }) {
console.log(p1, p2, p3)
}
f('p1', { p2: 'p2' })// p1 p2 bb
var obj = { a :"aaa", b:"bbb" }
var { b } = obj
console.log(b)//bbb
字符串解构:
let [a, b, c, d, e] = 'hello'
console.log(a, b, c, d, e) //h e l l o
方法: includes startsWith endsWith repeat 模板字符串:凡是以后需要字符串拼接的地方都使用模板字符串 如果是普通的字符串,就还是通过原来的 单引号 去定义
扩展
数组的扩展
//array.find()寻找某个元素和 array.findIndex()寻找某个值的下标
const arr = [
{ foo: 'a', name: 'aaa' },
{ foo: 'b', name: 'bbb' },
{ foo: 'b', name: 'bbc' },
{ foo: 'c', name: 'ccc' },
]
var item1 = arr.find(function(obj,index){
return obj.foo === 'b'
})
var item2 = arr.findIndex(function(obj,index){
return obj.foo === 'c'
})
console.log(item1) //{foo :'b',name:'bbb'}
console.log(item2)//3
//array.keys()遍历数组下标
let arr1 = ['a', 'b', 'c']
console.log(arr1.keys());
for(let index of arr1.keys()){
console.log(index);// 0 1 2
}
//不支持array.values()这个方法
for(let index of arr1.values()){
console.log(index);//报错
}
//array.entries()遍历数组
for(let [index,item] of arr1.entries()){
console.log(index);//0 1 2
console.log(item);// a b c
}
// 是否包含某个元素
console.log(arr1.includes('d'))//false
console.log(arr1.includes('a'))//true
字符串的扩展
let name = 'Jack'
let foo = `hello ${name} haha
大家好,我叫:${name}
调用函数:${f()}`
console.log(foo)
function f() {
return 'hello'
}
输出:
hello jack haha
大家好,我叫: jack
调用函数: hello
函数的扩展
// 默认值最好作为函数的最后一个参数
// 如果是前面的参数默认值,则不能省略,不能跳过
function f(x = 20, y = 10) {
console.log(x, y)
}
f()// 20,10
// ...args 叫做 rest 参数
// ...args 是一种语法,...不能省略,args 是随便起的一个名字
// ...args 可以将用户传递进来的参数包装到一个数组中
// ...args 是把用户传递参数的没有对应到具体形参的变量解析到一个数组中
function f(a, ...args) {
let sum = 0
for(let num of args) {
sum += num
}
console.log(sum)
}
f(1, 2, 3)//2+3 = 5
// ... 扩展运算符,可以将一个数组展开
let arr = [1, 2, 3]
console.log(...arr)// 1 2 3
let arr1 = [1,2]
let arr2 = [3,4]
let result = [...arr1, ...arr2]
console.log(result)//[1,2,3,4]
function f1(x, y, z) {
console.log(x, y, z)//1,2,3
}
var arr = [1, 2, 3]
f1.apply(null, arr)
f1(...arr)
补充apply 和call 的区别
apply
函数名.apply(obj, 数组or伪数组);
功能:
-1. 调用函数
-2. 改变this指向为第一个参数中的对象
-3. 将第二个参数的数组或者伪数组,中的元素一一拆解,依次传递给函数作为实参
call
函数名.call(obj, arg1...argN);
功能:
-1. 调用函数
-2. 改变this指向为第一个参数中的对象
-3. 将第二个及以后的所有参数,依次的传递给函数作为实参
注意事项:
-如果call和apply的第一个参数为null或者undefined,this将会指向window
-如果call和apply的第一个参数为值类型的数据,会将值类型的数据转换成其对应的引用类型的数据,this指向该引用类型的数据
tips: 一般情况下apply的传参特性会被使用的居多(转换伪数组为真数组,求最大值)
call , apply实现继承
function Person(name,age,love){
this.name=name;
this.age=age;
this.love=love;
this.say=function say(){
alert("姓名:"+name);
}
}
//call方式
function student(name,age){
Person.call(this,name,age);
}
//apply方式
function teacher(name,love){
Person.apply(this,[name,love]);
//Person.apply(this,arguments); //跟上句一样的效果,arguments
}
对象的扩展
// 对象属性成员的 get 和 set 方法适合做一些数据合法性校验
var xiaoming = {
name: 'lemon_zoey',
_age: 20,
get age () {
return this._age
},
set age (value) {
if (value < 0 || value > 100) {
throw new Error('这个数据不合法哦')
}
this._age = value
}
}
console.log(xiaoming.age)//20
console.log(xiaoming._age)//20
xiaoming.age = -1
console.log(xiaoming.age)//Uncaught Error: 这个数据不合法哦
// 获取一个对象所有键名数组
console.log(Object.keys(xiaoming))//name _age age
箭头函数
let f = function (v) {
return v
}
//等价于
let f = v => v
//如果有多个参数,必须加括号
let fn = (x, y) => x + y
// 如果方法体有多条执行语句,则必须加 {}
let add = (x, y) => {
console.log(x, y)
return x + y
}
// 箭头函数最好都用在匿名函数的地方
let arr = [1, 2, 3]
arr.forEach(n => console.log(n))
let newArr = arr.map(n => n + 1)
console.log(newArr)
// 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
function Person({ name = 'Jack', age = 18 }) {
this.name = name
this.age = age
}
Person.prototype.sayHello = function () {
setTimeout(() => {
console.log(`hello name: ${this.name}, age: ${this.age}`)
}, 1000)
}
var p1 = new Person({})
p1.sayHello() //hello name: jack,age: 18
// 不能作为构造函数使用
let F = (x, y) => {
return x + y
}
var f = new F(10, 20)// Uncaught TypeError: F is not a constructor
module
const fs = require('fs')
//Equivalent to
import fs from 'fs'
模块加载的不同种类
在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种,CommonJS 模块就是对象,输入时必须查找对象属性。
// CommonJS模块
let { stat, exists, readFile } = require('fs');
// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;
- ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
// ES6模块
import { stat, exists, readFile } from 'fs';
模块加载的好处。
- 静态加载带来的各种好处,效率高于common.js
- 不再需要UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。
- 将来浏览器的新 API 就能用模块格式提供,不再必须做成全局变量或者navigator对象的属性。 不再需要对象作为命名空间(比如Math对象),未来这些功能可以通过模块提供。
export
模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能
// profile.js
export var name= 'lemon_zoey';
export var age = '20'
//Equivalent to
var name = 'lemon_zoey'
export {name,age}
export命令除了输出变量,还可以输出函数或类(class)。
export function fn(a,b){
}
需要特别注意的是,export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系
// 报错,没有提供对外的接口
export 1;
// 报错,没有提供对外的接口
var m = 1;
export m;
//正确写法,它们的实质是,在接口名与模块内部变量之间,建立了一一对应的关系
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
import
使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。
import {firstName, lastName, year} from './index';
整体加载*
下面是一个index.js文件,它输出两个方法fn1和fn2。
// index.js
export function fn1(a) {
return a
}
export function fn2(b) {
return b
}
现在,加载这个模块
//main.js
import { fn1, fn2} from './index';//逐一加载
//Equivalent to
import * as index from './index'
console.log(index.fn1)//a
export default 命令
// export-default.js
export default function () {
console.log('foo');
}
// import-default.js
import customName from './export-default';
customName(); // 'foo'
//需要注意的是,这时import命令后面,不使用大括号。
注意:export 与 import 对应的需要加{} export default 与 import对应的不需要加{}