一、 ES6 基础语法
1.1 let
作用域就是一个变量的有用的局限,就是你声明一个变量今后,这个变量在什么场所能够运用它。之前JavaScript只需全局作用域和函数作用域,如今JavaScript也有了块级作用域(block scope)
1.1.1 let 语法
let var1 [= value1] [, var2 [= value2]] [, …, varN [= valueN]];
1.1.2 参数诠释
var1, var2, …, varN 变量名。能够是恣意正当的标识符。
value1, value2, …, valueN 变量的初始值。能够是恣意正当的表达式。
1.1.2 let 形貌
let许可你声明一个作用域被限定在块级中的变量、语句或许表达式。与var关键字差别的是,它声明的变量只能是全局或许全部函数块的。
1.1.3 let 作用域划定规矩
let声明的变量只在其声明的块或子块中可用,这一点,与var类似。两者之间最主要的区分在于var声明的变量的作用域是全部关闭函数。
看下面的例子:
function varTest() {
var x = 1;
if (true) {
var x = 2; // 一样的变量!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
if (true) {
let x = 2; // 差别的变量
console.log(x); // 2
}
console.log(x); // 1
}
1.2 const
1.2.1 const 语法
const name1 = value1 [, name2 = value2 [, … [, nameN = valueN]]];
1.2.2 参数诠释
nameN
常量称号,能够是恣意正当的标识符。
valueN
常量值,能够是恣意正当的表达式。
1.2.3 const形貌
此声明建立一个常量,其作用域能够是全局或当地声明的块。 与var变量差别,全局常量不会变成窗口对象的属性。须要一个常数的初始化器;也就是说,您必需在声明的统一语句中指定它的值(这是有原理的,因为今后不能变动)。
const声明建立一个值的只读援用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。比方,在援用内容是对象的情况下,这意味着能够转变对象的内容(比方,其参数)。
1.2.4 实例
<script>
const a = "123";
a = "234";
console.log(a);// 会失足 Uncaught TypeError: Assignment to constant variable.
const arr = [1,2,3];
arr.push(4);
console.log(arr);// [1,2,3,4]
arr = [];
console.log(arr);// 转变数组的指向会失足 Uncaught TypeError: Assignment to constant variable
</script>
1.2.5 小结
假如const背面的变量是平常变量,转变值报错。假如背面存储的是数组或许对象,那末转变它的指向也会报错,然则假如转变数组或许对象的值是不会发作毛病的
1.3 解构赋值
ES6许可依据肯定形式,从数组和对象中提取值,对变量举行赋值,这被称为解构
1.3.1 数组的解构赋值
- ES5 中的变量赋值,只能直接指定值
var a = 1;
var b = 2;
var c = 3;
- ES6 能够如许写
var [a, b, c] = [1, 2, 3];
console.log(a,b,c);// 1 2 3
上面代码示意,能够从数组中提取值,依据对应位置,对变量赋值。这类写法属于“形式婚配”,只需等号双方的形式雷同,左侧的变量就会被给予对应的值
1.3.2 许可运用默许值
var [a=1] = []
console.log(a);// 1
var [a,b=2] = [3];
console.log(a,b);//3 2
var [a,b=4] = [5,undefined];
console.log(a,b);// 5 4
1.3.4 运用默许值的注重事项
注重一:
ES6内部运用严厉相称运算符(===),推断一个位置是不是有值。 所以,假如一个数组成员不严厉即是undefined,默许值是不会见效的。
var [d=8] = [undefined];
console.log(d);// 8
var [a=9] = [null];
console.log(a);// null
上面代码中,假如一个数组成员是null,默许值就不会见效,因为null不严厉即是undefined。
注重二:
假如默许值是一个表达式,那末这个表达式是惰性求值的,即只需在用到的时刻,才会求值。
function getNumber(){
console.log("只需用到我的时刻我才涌现");
}
var [a=getNumber()] = ["我先来"];
console.log(a);// 会输出 我先来
上面代码中,因为a能取到值,所以函数f基础不会实行。上面的代码实在等价于下面的代码。
function getNumber(){
console.log("只需用到我的时刻我才涌现");
}
let a;
if(["我先来"][0]===undefined){
a = getNumber();
}else{
a = ["我先来"][0];
}
console.log(a);// 会输出 我先来
注重三:
默许值能够援用解构赋值的其他变量,但该变量必需已声明
let [a,b=a]=[1];
console.log(a,b);// a = 1 b = 1
let [x=2,y=x]=[];
console.log(x,y);// x = 2 y = 2
let [c=1,d=c]=[12,3];
console.log(c,d);// c =12 d = 3
let [e=f,f=1]=[];
console.log(e,f);// 报错 f is not defined
上面末了一个表达式之所以会报错,是因为e用到默许值f时,f还没有声明
1.3.5 对象的解构赋值
解构赋值不仅能够用于数组,还能够用于对象.
eg:
let {name,age} = {name:"wxk",age:20};
console.log(name); // wxk
注重:对象的解构与数组有一个主要的差别
- 数组的元素是按序次分列的,变量的取值由它的位置决议 - 对象的属性没有序次,变量必需与属性同名,才取到准确的值
小编总结:等号左侧的变量的序次,与等号右侧两个同名属性的序次不一致,然则对取值完整没有影响。然则假如变量没有对应的同名属性,则会致使取不到值,末了即是undefined
1.4 函数
1.4.1 为函数的参数设置默许值
在es6内里我们能够给定义的函数吸收的参数设置默许的值,假如不去指定这个函数的参数的值的话,就会运用这些参数的默许的值
function Person(name="Tom",age=12){
console.log(name);//Tom
console.log(age);// 12
}
Person();
假如在挪用函数的时刻传入实参,则会转变默许参数的值。eg:
function Person(name="Tom",age=12){
console.log(name);//Jack
console.log(age);// 20
}
Person("Jack",20);
1.4.2 … 操纵符
…是es6中新增加的一种操纵符,能够叫做spread(扩大)或则rest(盈余)
详细用法以下:
- rest (盈余操纵符)
盈余操纵符平常会用在函数的参数内里。比方:
想让一个函数支撑更多的参数,参数的数目不受限定,这个时刻就能够 运用盈余操纵符。
eg:
<script>
function restName(first,second,...third){
console.log(first);// Tom
console.log(second);// Jack
console.log(third);// [Emma Edith May]
}
restName("Tom","Jack","Emma","Edith","May");
</script>
盈余操纵符背面的变量会变成一个数组,过剩的参数会被放入这个数组中
- spread(扩大运算符)
…操纵符假如用在数组的前面,作用就是将这个数组睁开,因而称为扩大操纵符。相当于rest操纵符的逆运算
eg:
<script>
let arr1 = ["Tom","Jack","Emma","Edith","May"];
let arr2 = ["Haliey","Lvy"];
let arr3 = [...arr1,...arr2];
console.log(arr3);
</script>
这里呢把数组arr1 和 数组 arr2 用 … 操纵符举行了扩大,一切他们变成了字符串,不信你们能够尝试一下,直接输出 console.log(…arr1)
1.4.3 函数的 name 属性
es6给函数增加了一个name属性,运用这个属性我们能够获得函数的名字
eg:
<script>
function getName(){}
console.log(getName.name);// getName;
</script>
1.4.4 箭头函数(重点)
箭头函数的语法
- 不引入参数
<script>
// ES5 语法
var sum = function(){
return 1 + 2;
}
// 等同于
// ES6 语法
var sum = ()=> 1 + 2;
console.log(sum());// 3
</script>
2. 引入单个参数
<script>
//ES5 语法
var refelect = function(value){
return value;
}
// 等同于
// ES6
var refelect = (value)=> value;
console.log(refelect(144155));// 144155
</scripte>
3. 引入多个参数,则应加上小括号
// ES5 语法
function sum(num1,num2){
return num1 + num2;
}
// 等同于
// ES6 语法
var sum = (num1,num2)=> num1 + num2;
console.log(sum(5,9));//14
4. 若你想运用规范的函数体,或许函数体内可能有更多的语句要实行,则要用大括号将函数体括起来,并邃晓定义返回值。
// ES6 语法
var sum = (num1, num2) => { return num1 + num2; }
//等同于:
// ES5 语法
var sum = function(num1, num2) {
return num1 + num2;
};
5. 箭头函数若要返回自定义对象的话,就必需用小括号把该对象括起来先
<script>
// 定义一个函数表达式,返回一个对象 这是ES5语法
var person = function(name){
return {
name: "Tom",
age: 20
};
};
// 等同于 下面ES6 语法
var person = (name)=>({name: "Tom",age: 20})
console.log(person().name);// Tom
</script>
1.4.5 箭头函数的 this 指向
箭头函数本身是没有this和arguments的,在箭头函数中援用this实际上是挪用的是定义时的上一层作用域的this。
这里强调的是上一层作用域,是因为对象是不能构成自力的作用域的。
看下面的小例子更轻易邃晓:
eg1
<script>
var obj = {
say: function() {
var f1 = ()=>{
console.log("1111",this);
}
f1();
}
}
var o = obj.say;
o();//f1实行时,say函数指向window,所以f1中的this指向window
obj.say();//f1实行时,say函数指向obj,所以f1中的this指向obj;
</script>
eg2:
var ojb = {
pro: {
getPro: ()=>{
console.log(this);
}
}
}
ojb.pro.getPro();//this指向的是window,因为箭头函数定义时,getPro的上一级是pro,是一个对象,不能构成零丁的作用域,故指向window。
总结箭头函数的this指向:箭头的this,向上找,找到非箭头函数,看一下这个非箭头函数的this是谁,那末箭头函数的this就是这个非箭头函数的this。
1.5 字符串
1.5.1 includes(), startsWith(), endsWith()
传统上,JavaScript只需indexOf要领,能够用来肯定一个字符串是不是包括在另一个字符串中。ES6又供应了三种新要领。
includes():返回布尔值,示意是不是找到了参数字符串。
startsWith():返回布尔值,示意参数字符串是不是在源字符串的头部。
endsWith():返回布尔值,示意参数字符串是不是在源字符串的尾部。
举例说明三个要领怎样用:
<script>
var string = "我喜好的人喜好我";
console.log(string.includes("喜好"));// true
console.log(string.startsWith("我"));// true
console.log(string.endsWith("喜好"));// false
</script>
注重:这三个要领都支撑第二个参数,示意最先搜刮的位置
1.5.2 模板字符串
模板字符串中一切的空格、新行、缩进,都邑原样输出在天生的字符串中
<script>
// 之前我们将变量和字符串举行衔接时的写法是如许的:
var str1 = "Hello";
var str2 = "World";
var str3 = str1 +str2 + "前端工程师";
console.log(str3);//HelloWorld前端工程师
// ES6 中的写法是如许的,很简朴
var str4 = `前端工程师${str1},${str2}`;
console.log(str4);// 前端工程师Hello,World
</script>
注重:模板字符串(template string)是增强版的字符串,用反引号(`),标识,嵌入的变量名写在${}当中
1.6 对象 Object
1.6.1 属性的简约示意法
<script>
// 之前在对象内里增加跟已定义的变量名字雷同的属性以下:
var name= "Tom";
var age= 20;
var person= {
name:name,
age:age
}
console.log(person.name);// Tom
console.log(person.age);// 20
// ES6 给出了简朴的写法,在对象内里直接加上这属性, 不须要再指定值
var color= "red";
var weight= 50;
var animal = {
color,
weight
}
console.log(animal.color);// red
console.log(animal.weight);// 50
</script>
ES6为我们供应了一种简写要领,就是在对象内里直接加上这属性,不须要再指定值
1.6.2 对象新增函数Object.is()
ES5比较两个值是不是相称,只需两个运算符:相称运算符(==)和严厉相称运算符(===)。它们都有瑕玷,前者会自动转换数据类型,后者的NaN不即是本身,以及+0即是-0。JavaScript缺少一种运算,在一切环境中,只需两个值是一样的,它们就应该相称。
ES6提出“Same-value equality”算法,用来处置惩罚这个题目。Object.is就是布置这个算法的新要领。它用来比较两个值是不是严厉相称,与严厉比较运算符(===)的行动基础一致。
见下面的例子:
<script>
console.log(+0 === -0);// true 在数学上两者是不等的
console.log(NaN === NaN);// false 理论上是相称的,然则在ES5中是不等的 ,这时候ES6 就有了一个要领特地针对这些 bug ,那就是 is()
console.log(Object.is(+0 , -0));// false
console.log(Object.is(NaN , NaN));// true
</script>
1.6.3 对象新增函数Object.assign()
Object.assign要领用于对象的兼并,将源对象(source)的一切可罗列属性,复制到目的对象(target)
<script>
// 定义一个person 对象
var person = {
name:"Tom",
age:20
}
// 定义一个门生对象
var student = {
stu: "前端",
moy: "10k"
}
var obj = {}
// assign 第一参数为目的对象,背面的为源对象
Object.assign(obj,person,student);
console.log(obj);
</script>
1. 注重:假如目的对象与源对象有同名属性,或多个源对象有同名属性,则后 面的属性会掩盖前面的属性
<script>
// 定义一个person 对象
var person = {
name:"Tom",
age:20
}
// 定义一个门生对象
var student = {
name:"Jack",
stu: "前端",
moy: "10k"
}
var obj = {
}
Object.assign(obj,person,student);
console.log(obj);//{name: "Jack", age: 20, stu: "前端", moy: "10k"}
</script>
2. 假如只需一个参数,Object.assign会直接返回该参数
var cat = {
height:50
}
var str = {}
Object.assign(str,cat);
console.log(str);//{height: 50}
3. 假如该参数不是对象,则会先转成对象,然后返回
console.log(Object.assign(2));// Number {2}
4. 因为undefined和null没法转成对象,所以假如它们作为参数,就会报错。
1.7 鸠合对象
1.7.1 Set 对象
Set对象是一组值的鸠合,这些值是不反复的,无序的,与我们在数学中学到的鸠合是一样的。我们能够往内里增加、删除、查询数据
1. 先声明一个Set对象
var mySet = new Set();
2. 往这个鸠合对象中增加元素
mySet.add(1);
mySet.add(“some text”);
3. 推断鸠合中是不是存在一个元素1
mySet.has(1); // true 返回一个布尔值,示意该值在Set中存在与否。
4. 删除鸠合中的字符串
mySet.delete(“foo”);//移除Set的中与这个值相称的元素
5. 猎取鸠合中元素的数目
mySet.size; // 返回Set对象的值的个数。
6. 删除鸠合中一切的元素
mySet.clear();//移除Set对象内的一切元素。
<script>
//声明一个set对象
var mySet = new Set();
// 向鸠合中增加元素
mySet.add(123);
mySet.add("前端");
mySet.add("全栈");
console.log(mySet);
// 推断该对象中是不是存在123
var a = mySet.has(123);
console.log(a);// true
// 删除该对象中的 123
mySet.delete(123);
console.log(mySet);
// 猎取元素的数目 size
var b = mySet.size;
console.log(b);
// 删除鸠合中一切的元素
mySet.clear();
console.log(mySet);
</script>
1.7.2 Map对象
假如你须要一个键值对的数据结构,我们能够声明一个Map对象,这个对象内里能够包括多个项目,每一个项目都有一个名字,另有一个跟它对应的值
1. 建立Map对象的要领是运用new操纵符去声明这个对象
var myMap = new Map();
2. 向Map对象内里增加键值对,其中键和值能够是恣意值(对象或许原 始值)
var obj = {};
var fun = function(){};
var str = “HelloWorld”;
myMap.set(obj, “我是对象”);
myMap.set(fun, “我是函数”);
myMap.set(str, “我是字符串”);
3. 检察鸠合中元素的数目
myMap.size
4. 猎取响应的键值
myMap.get(obj);
5. 删除一个键值对,然后再推断该键值对是不是存在
myMap.delete(fun);
myMap.has(fun);
6. 删除Map鸠合中一切的键值对
myMap.clear();
eg:
<script>
// 建立一个Map 对象
var myMap = new Map();
// 向对象中增加数据
var obj = {
name: "Tom",
age: 25
}
var str = "前端工程师";
var sum = function(a,b){
return a + b;
}
myMap.set(obj,obj.name);
myMap.set(str,"前端工程师");
myMap.set(sum,sum(2,4));
console.log(myMap);
</script>
其他的要领就不演示了,和上面的Set要领一样
1.7.3 Class (重点)
<script>
//ES5 中运用面向对象是如许的
function person(name,age){
this.name = name;
this.age = age;
this.run = function(){
console.log("天天对峙磨炼");
}
}
// 实例化一个对象
var student = new person("Tom",20);
student.run();// 会输出 天天对峙磨炼
</script>
ES6供应了更靠近传统言语的写法,引入了Class(类)这个观点,作为对象的模板。经由过程class关键字,能够定义类。基础上,ES6的class能够看做只是一个语法糖,它的绝大部分功用,ES5都能够做到,新的class写法只是让对象原型的写法越发清楚、更像面向对象编程的语法罢了。上面的代码就能够如许改
class person {
constructor(name,age){
this.name = name;
this.age = age;
}
run(){
console.log("天天对峙磨炼");
}
}
var student = new person("Jack",15);
student.run();
小编剖析:上面代码定义了一个“类”,能够看到内里有一个constructor要领, 这就是构造要领,而this关键字则代表实例对象。也就是说,ES5的构造函数person,对应ES6的person类的构造要领。person类除了构造要领,还定义了一个run要领。注重,定义“类”要领的时刻,前面不须要加上function这个关键字,直接把函数定义放进去了就能够了。别的,要领之间不须要逗号分开,加了会报错。构造函数的prototype属性,在ES6的“类”上面继续存在。事实上,类的一切要领都定义在类的prototype属性上面
1.7.4 class继续 (重点)
<script>
// 定义一个猫科动物
class Felidae{
constructor(color,weight){
this.color = color;
this.weight = weight;
}
eat(){
console.log("吃肉");
}
}
// 定义一个猫类,并继续猫科动物的一些特性
class Cat extends Felidae {
constructor(color,weight,height){
super(color, weight);
this.height = height;
}
silly(){
console.log("萌萌的猫咪很可爱!");
}
}
// 实例化一个Kitty猫
var Kitty = new Cat("pink",20,30);
Kitty.silly();
</script>
extends关键字用于完成类之间的继续。子类继续父类,就继续了父类的一切属性和要领,运用super能够挪用父类的要领
1.8 Promise对象
1.8.1 什么是Promise对象
一个 Promise 对象能够理解为一次将要实行的操纵(常常被用于异步操纵),运用了 Promise 对象以后能够用一种链式挪用的体式格局来构造代码,让代码越发直观。而且因为 Promise.all 如许的要领存在,能够让同时实行多个操纵变得简朴
下面简朴引见Promise 对象,以下代码:
<script>
function HelloWorld(ready){
return new Promise(function(resolve,reject){
if(ready){
resolve("HelloWorld");
}else{
reject("GoodBay");
}
});
}
HelloWorld(true).then(function(message){
console.log(message);
},function(error){
console.log(error);
});
</script>
上面的代码完成的功用异常简朴,helloWord 函数接收一个参数,假如为 true 就打印 “Hello World!”,假如为 false 就打印毛病的信息。helloWord 函数返回的是一个 Promise 对象。
在 Promise 对象当中有两个主要要领————resolve 和 reject。
resolve 要领能够使 Promise 对象的状况转变成胜利,同时通报一个参数用于后续胜利后的操纵,在这个例子当中就是 Hello World!字符串
reject 要领则是将 Promise 对象的状况转变成失利,同时将毛病的信息通报到后续毛病处置惩罚的操纵
1.8.2 Promise的三种状况
- resolved 能够理解为胜利的状况
- rejected 能够理解为失利的状
- pending promise对象实例建立时刻的初始状况
helloWorld 的例子中的 then 要领就是依据 Promise 对象的状况来肯定实行的操纵,resolve 时实行第一个函数(onFulfilled),reject 时实行第二个函数(onRejected)
怎样检察Promise对象的要领,在控制台输出 new Promise(function(){})
见下图:
### 1.8.3 运用Promise处置惩罚多任务
看下面的例子:
function HelloWorld(ready){
return new Promise(function(resolve,reject){
if(ready){
resolve("HelloWorld");
}else{
reject("GoodBay");
}
});
}
HelloWorld(true).then(function(message){
console.log(message);
},function(error){
console.log(error);
}).then(function(){
console.log("你好,天下!");
}).then(function(){
console.log("讲真的");
});
剖析:能够看到背面的要领用了链式的体式格局举行编程,这是因为,then返回的照样一个 Promise 对象,因而返回的对象依旧具有 then 要领,而且返回的对象状况是 resolved, 所今背面的 then要领全部是实行then 要领中的第一个函数参数
1.8.4 catch要领
<script>
function Cat(ready){
return new Promise(function(resolve,reject){
if(ready){
resolve("Tom");
}else{
reject("Kitty");
}
})
}
Cat(false).then(function(value1){
console.log(value1)
}).catch(function(){
console.log("此时实行的是then要领中的第二个函数参数");
});
</script>
catch 要领是 then(onFulfilled, onRejected) 要领当中 onRejected 函数的一个简朴的写法,也就是说能够写成then(fn).catch(fn),相当于 then(fn).then(null, fn)。运用 catch 的写法比平常的写法越发清楚邃晓
1.8.5 all和race要领
console.time();
var p1 = new Promise(function(resolve) {
setTimeout(function() {
resolve("Hello");
}, 3000);
});
var p2 = new Promise(function(resolve) {
setTimeout(function() {
resolve("world");
}, 3000);
})
Promise.all([p1, p2]).then(function(result) {
console.log(result);
console.timeEnd();
});
上面的例子模拟了传输两个数据须要差别的时长,虽然 p2 的速率比 p1 要快,然则 Promise.all 要领会依据数组内里的递次将效果返回
一样平常开辟中经常会碰到如许的需求,在差别的接口要求数据然后拼合成本身所需的数据,一般这些接口之间没有关联(比方不须要前一个接口的数据作为后一个接口的参数),这个时刻 Promise.all 要领就能够派上用场了
另有一个和 Promise.all 相类似的要领 Promise.race,它一样吸收一个数组,差别的是只需该数组中的 Promise 对象的状况发作变化(无论是 resolve 照样 reject)该要领都邑返回
1.9 fetch收集要求
与ajax 要求的对照见下面的代码:
<script>
// ajax 收集要求
var xhr = new XMLHttpRequest();
xhr.open("get", url, true);
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
}
// fetch 中的 get 要求
fetch(url).then(function(data) {
return data.json();
}).then(function(data) {
console.log(data);
}).catch(error){
console.log(error)
};
// fetch 中的 post 要求
fetch(url, {
method: "post",
mode: 'same-origin',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: "a=1&b=2"
}).then(function(data) {
// return data.json();
}).then(function(data) {
// console.log(data);
})
</script>
假如有须要能够依据上面的体式格局举行编写
二、ES6之Module体系
2.1 为何要举行模块化?
- 可维护性的须要
- 可测性的须要
- 机能的须要
- 架构的需求
- 代码复用
- 多人合作的须要
2.2 导入导出
小编这里只说步骤:
第一步:在你须要导出的 js 文件中某个要领或对象时,前面加上 export 关键字
第二步: 在另一个js文件中导入你要导出的js文件,import 对象/要领 from ×××.js
第三步: 在html中引入进口js 文件,就是第二步中的另一个js文件。
<script src=”.js” type=”module”><script>,这里的type属性肯定要加上
三、总结
上面的ES6 学问并非很全,另有其他的一部分,故意的小伙伴能够本身去进修!