ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会)在标准ECMA-262中定义的脚本语言规范。
Es6
Let与Const
ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
let
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
const
const就是constant的缩写,用于声明一个只读的常量。一旦声明,常量的值就不能改变,即不可变量。const定义常量的原理是阻隔变量名所对应的内存地址被改变。
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
类
ES6 引入了class(类),让JavaScript的面向对象编程变得更加简单和易于理解。
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
ES6 的class可以看作只是一个语法糖,上面的代码用 ES6 的class改写,就是下面这样。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
模块化
ECMAScript包含了以往模块加载库的主要功能,还添加了一些非常使用的设计,以提高ECMAScript的模块化管理功能。
(1)引入模块(import)
ES Module中有很多种引入模块的方法,最基本的便是import语句。
import name form 'module-name'
import * as name from 'module-name'
import {member} from 'module-name'
import {meber as alias} from 'module-name'
import 'module-name'
从模块中局部引用的接口定义一个别名,以避免指代不明或接口重名的情况出现。
import {createServer as createHTTPServer} from 'http'
import {createServer as createHTTPSServer} from 'https'
(2)暴露模块(export)
暴露单一接口
如果需要定义一个项目内的工具集模块,需要将其中定义的函数或者对象暴露到该文件所定义的模块上。
//module.js
export const apiRoot='http://example.com/api'
export function method(){
//...
}
export class foo{
//...
}
//app.js
import {method,foo} from 'module.js'
暴露模块默认接口
在某些时候,一个模块只需要暴露一个接口,比如需要使用模块机制定义一个只含有一个单一工具类的模块时,就没有必要让这个工具类成为该模块的一部分,而是让这个类成为这个模块。
//client.js
export default class Client{
//...
}
//app.js
import Client from 'client.js'
混合使用暴露接口语句
开发者可以为一个模块同时定义默认接口和其它命名接口。
//module.js
export default class Client{
//...
}
export const foo='bar'
//app.js
import Client,{foo} from 'module'
延展操作符(…)
扩展运算符(spread)是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
//例子1
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
//不使用延展操作符
console.log(sum.apply(null, numbers));//通过 apply() 方法,您能够编写用于不同对象的方法。
//使用延展操作符
console.log(sum(...numbers));// 6
//例子2:构造数组
const stuendts = ['Jine','Tom'];
const persons = ['Tony',... stuendts,'Aaron','Anna'];
conslog.log(persions)// ["Tony", "Jine", "Tom", "Aaron", "Anna"]
//例子3:数组拷贝
var arr = [1, 2, 3];
var arr2 = [...arr]; // 等同于 arr.slice()
arr2.push(4);
console.log(arr2)//[1, 2, 3, 4]
//例子4:连接多个数组
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
var arr3 = [...arr1, ...arr2];// 将 arr2 中所有元素附加到 arr1 后面并返回
//等同于
var arr4 = arr1.concat(arr2);
//例子4:对象的扩展
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
var clonedObj = { ...obj1 };
// 克隆后的对象: { foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 };
// 合并后的对象: { foo: "baz", x: 42, y: 13 }
箭头函数(=>)
箭头函数,顾名思义便是使用箭头(=>)进行定义的函数,属于匿名函数(Anonymous Function)一类。
相对于传统的function语句,箭头函数在简单函数使用中更为简洁直观。
var sum = (num1, num2) => { return num1 + num2; }
//等同于
var sum = function(num1, num2) {
return num1 + num2;
};
函数参数默认值
ES6支持在定义函数的时候为其设置默认值:
function foo(height = 50, color = 'red')
{
// ...
}
不使用默认值:
function foo(height, color)
{
var height = height || 50;
var color = color || 'red';
//...
}
```js
## 模板字符串
当我们使用普通的字符串时,会使用单引号或双引号来包裹字符串的内容,在ES2015的模板字符串中使用反勾号`。
```js
var name = 'Your name is ' + first + ' ' + last + '.'
//使用模板字符串:
var name = `Your name is ${first} ${last}.`
在ES6中通过${}就可以完成字符串的拼接,只需要将变量放在大括号之中。
解构赋值
解构赋值语法是JavaScript的一种表达式,可以方便的从数组或者对象中快速提取值赋给定义的变量。
获取数组中的值
从数组中获取值并赋值到变量中,变量的顺序与数组中对象顺序对应。
//例1
let a = 1;
let b = 2;
let c = 3;
//ES6 允许写成下面这样。
let [a, b, c] = [1, 2, 3];
//例2
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
//例3:如果你要忽略某些值,你可以按照下面的写法获取你想要的值
var [first, , , last] = foo;
console.log(first); // "one"
console.log(last); // "four"
//例4
let [x, , y] = [1, 2, 3];
x // 1
y // 3
//例5:
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
//例6
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
如果解构不成功,变量的值就等于undefined。
let [foo] = [];
let [bar, foo] = [1];
不完全解构
let [x, y] = [1, 2, 3];
x // 1
y // 2
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
如果没有从数组中的获取到值,你可以为变量设置一个默认值。
var a, b;
[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7
通过解构赋值可以方便的交换两个变量的值。
var a = 1;
var b = 3;
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
获取对象中的值
解构不仅可以用于数组,还可以用于对象。
//例子1
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
//例子2
const student = {
name:'Ming',
age:'18',
city:'Shanghai'
};
const {name,age,city} = student;
console.log(name); // "Ming"
console.log(age); // "18"
console.log(city); // "Shanghai"
对象属性简写
在ES6中允许我们在设置一个对象的属性的时候不指定属性名。
不使用ES6
const name='Ming',age='18',city='Shanghai';
const student = {
name:name,
age:age,
city:city
};
console.log(student);//{name: "Ming", age: "18", city: "Shanghai"}
//使用ES6
const name='Ming',age='18',city='Shanghai';
const student = {name,age,city};
console.log(student);//{name: "Ming", age: "18", city: "Shanghai"}
Promise
Promise意在让异步代码变得干净和直观,让异步代码变得井然有序。
Promise在设计上具有原子性,即只有三种状态:等待(Pending)、成功(Fulfilled)、失败(Rejected)。在调用支持Promise的异步方法时,逻辑变得非常简单,在大规模的软件工程开发中具有良好的健壮性。
下面代码创造了一个Promise实例。
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
下面是一个Promise对象的简单例子。
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
});
上面代码中,timeout方法返回一个Promise实例,表示一段时间以后才会发生的结果。过了指定的时间(ms参数)以后,Promise实例的状态变为resolved,就会触发then方法绑定的回调函数。
Es7
求幂运算符(**)
在 ES7 中引入指数运算符 ** ,用来实现幂运算,功能与 Math.pow 相同,这个运算符是简化版的 Math.pow(x, y)。
5**2 //25
3**2 //9
注意任何数字,包括 NaN,它的0次幂都是1。如果指数是NaN,结果总是NaN,无论底数是什么。
9**0 //1
99**NaN //NaN
Array.prototype.includes()方法
includes()作用,是查找一个值在不在数组里,若是存在则返回true,不存在返回false.
1.基本用法:
['a', 'b', 'c'].includes('a') // true
['a', 'b', 'c'].includes('d') // false
2.接收俩个参数:要搜索的值和搜索的开始索引
['a', 'b', 'c', 'd'].includes('b') // true
['a', 'b', 'c', 'd'].includes('b', 1) // true
['a', 'b', 'c', 'd'].includes('b', 2) // false
fromIndex 参数值也可以为负数,那样从倒数第N个位置开始搜索指定的值。
[‘a’, ‘b’, ‘c’, ‘d’].includes(‘b’,-2) // false
[‘a’, ‘b’, ‘c’, ‘d’].includes(‘c’, -2) // true
Es8
async/await
Object.values()
Object.values()方法返回一个给定对象中所有可枚举属性值的数组,值的顺序与使用
const person = { name: 'Fred', age: 87 }
Object.values(person) // ['Fred', 87]
返回数组的成员顺序,与属性的遍历部分介绍的排列规则一致
const obj = {100 : "a", 2 : "b", 7 : "c"};
console.log(Object.values(obj)); //["b", "c", "a"]
属性名为数值的属性,是按照数值大小,从小到大遍历的,因此返回的顺序是b、c、a。
Object.values() 也适用于数组
const people = ['Fred', 'Tony']
Object.values(people) // ['Fred', 'Tony']
Object.entries()
Object.entries方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组
传入对象
var obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj));
传入数组
const arr = [1, 2, 3];
console.log(Object.entries(arr)); // [['0', 1], ['1', '2'], ['2', '3']]
传入json数组
const arr = [1, 2, 3];
console.log(Object.entries(arr)); // [['0', 1], ['1', '2'], ['2', '3']]
传入对象
var obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj));
传入对象
var obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj));
字符串填充(padStart 和 padEnd)
字符串填充的目的是 向字符串添加字符,使字符串达到指定的长度。ES2017引入了两个 String 方法:padStart() 和 padEnd() 。
padStart()用于头部补全,padEnd()用于尾部补全。
'a'.padStart(4,"bc") //结果:bcba
'a'.padEnd(4,"bc") //结果:abcb
如果本身长度超过补全长度,则不变化
'aaa'.padStart(2,"bc") //结果:aaa
'aaa'.padEnd(2,"bc") //结果:aaa
如果不填写第二个补全内容参数,默认用空格补全
'a'.padStart(2) //结果:' a'
'a'.padEnd(2) //结果:'a '