简介
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准
let const
声明变量的关键字
特点
- 没有变量提升
不能在未声明之前使用- 形成块作用域
声明的变量只在当前它所在的代码块有效,可以使用- 不可重复声明
- 不污染全局变量
使用场景
// 作用1:for循环const arr=[]for(let i=0 ; i<9;i++){arr[i]=function(){return i;}}console.log(arr[5]()); //5const arr=[]for(var i=0 ; i<9;i++){arr[i]=function(){return i;}}console.log(arr[5]()); //9//作用2:不会污染全局变量// console.log(window.RegExp); //fn// var RegExp=10;// console.log(window.RegExp); //10console.log(window.RegExp); //fnlet RegExp=10;console.log(window.RegExp); //fn
模板字符串
before:
box.innerHTML='<li>'+name+'</li>'
after:
用于字符串拼接,当拼接有变量存在的时候 ,更加方便
//模板字符串 ``,插入变量使用${},利于拼接字符串const box=document.querySelector('.box')const name='adefhb'box.innerHTML=`<ul><li><span>${name}</span></li></ul>`
数据类型
map
键值对
- 增
set - 删
delete - 改
set - 查
get,has - 遍历
let map = new Map()//1.添加map.set('name','张三')map.set('age',18)//2.删除map.delete('name')//3.修改map.set('name','李四')//4.查找console.log(map.get('name'))console.log(map.has('name'))//5.遍历for(let key of map.keys()){console.log(key)}for(let value of map.values()){console.log(value)}console.log("///");for(let item of map.entries()){console.log(item[0],item[1])}
set
无重复值的列表
let set= new Set()console.log(set);//1.加元素set.add(1)set.add(2)set.add([3,4])set.add(4)set.add(4)//重复的元素不会被添加// //2.删除元素// set.delete(2)// //3.判断当前是否有1 --- true/false// console.log(set.has(1));//4.集合长度// console.log(set.size);// //5.遍历// set.forEach((value,key)=>{// console.log(value,key);// //val == key(set 中没有键 , 所以key 就是val)// })//6.set 转数组// let arr= Array.from(set)// console.log(arr); // [1, 2, Array(2), 4]// let arr2=[...set] // 展开运算符// console.log(arr2);//7.缺点 set 中对象的引用无法释放掉let obj={}let set2=new Set()set2.add(obj)// obj=nsull // 释放掉objectset2.delete(obj) // 可以释放掉了console.log(set2);//解决方法 WeakSet() --- 也释放不了// let weakSet= new WeakSet()// weakSet.add(obj)// weakSet.add({})// obj=null // 释放掉object// console.log(weakSet);
symbol
//原始数据类型 , 代表的是独一无二的值const a=Symbol('name')const b=Symbol('name')console.log(a);//Symbol(name)console.log(a===b);//false//用于定义对象的私有变量let obj={}obj.age="adffegg"obj[a]='asdf' //[]添加属性console.log(obj[a]);//使用[] 取值//因为是私有的所以没有输出// for(let key in obj)// {// console.log(key); // 未输出[a]// }// console.log(Object.keys(obj)); //为输出[a]//如何获取Symbol声明的属性名 输出私有的//1.let s=Object.getOwnPropertySymbols(obj)console.log(s); //只输出[Symbol(name)]//2.let m=Reflect.ownKeys(obj)console.log(m);//输出所有的 ['age', Symbol(name)]
class
构造类
//es5 造类function Person(name,age){this.name=name;this.age=age;}Person.prototype.sayName=function(){console.log(this.name);}//es6 造类class Person{//原型上的方法 new 的时候, 立即调用constructor(name,age){this.name=name;this.age=age;}// //添加方法// sayName(){// console.log(this.name);// }}//一次性添加多个方法Object.assign(Person.prototype,{sayName(){console.log(this.name);},sayAge(){console.log(this.age);}})
类的继承
class Student extends Person{constructor(name,age,grade){super(name,age);// Person.call(this,name,age);this.grade=grade;}//重写父类的方法sayAge(){console.log(this.age+1);}sayGrade(){console.log(this.grade);}}
函数
函数参数默认值
//1.es5 带参数默认值的函数function add(a,b){a=a||10b=b||20console.log(a+b);}add()add(90,1)//2.es6 带参数默认值函数function add2(a=10,b=20){console.log(a+b);}//es6 默认的表达式也可以是一个函数function add3(a,b=getVal(5)){console.log(a+b);}function getVal(num){return num;}add3(10)add3(10,10)
剩余参数
-
函数剩余参数 : …+具名参数 解决arguments问题
-
arguments 伪数组,函数内部使用,收集函数参数
//es5let book={title:"book",author:'小马哥',year:2019}let bookData= pick(book,'title','year')console.log(bookData);function pick(obj){let res={}console.log("///",arguments);//Array[{},'author','year']for(let i=1;i<arguments.length;i++){res[arguments[i]]=obj[arguments[i]]}return res;}//es6 : ...+一个具名参数let bookData2= pick2(book,'title','year')function pick2(obj,...args){console.log(args);//['title','year']let res={}for(let i=0;i<args.length;i++){res[args[i]]=obj[args[i]]}return res;}console.log("bookdata2",bookData2);
扩展运算符
- … 分割数组,对象,将各个项作为分离的参数传给函数
//eg:求数组的最大值const arr=[10,20,50,100,30,40,50]//1.使用applyconsole.log(Math.max.apply(null,arr));//2.使用扩展运算符console.log(Math.max(...arr));
箭头函数
this 指向问题
es5
//this 指向函数的调用者let PageHandle={id:123,init:function(){document.addEventListener('click',function(){console.log(this); // documentthis.doSomethings(); //TypeError: this.doSomethings is not a function})},doSomethings:function(){console.log("我被调用了");}}PageHandle.init();//es5 解决this指向问题let PageHandle={id:123,init:function(){document.addEventListener('click',function(){console.log(this); // documentthis.doSomethings(); //TypeError: this.doSomethings is not a function}.bind(this))},doSomethings:function(){console.log("我被调用了");}}PageHandle.init();
es6_655">es6
箭头函数 没有this指向:当前作用域没有this,从上级作用域链中寻找
let PageHandle={id:123,init:function(){document.addEventListener('click',()=>{console.log(this); // PageHandle//箭头函数的this指向函数定义时所在的对象this.doSomethings();})},doSomethings:function(){console.log("我被调用了");}}PageHandle.init();// es6 箭头函数注意事项// 1.不能作为构造函数let Person=()=>{};let person=new Person(); //TypeError: Person is not a constructor// 2.不能使用argumentslet add=(a,b)=>{console.log(arguments);}add(1,2,3); //ReferenceError: arguments is not defined
数组扩展方法
Array.from()
方法用于将伪数组转为真正的数组
// Array.from()方法用于将伪数组转为真正的数组
function add() {
// ES5 的写法,不宜阅读
var arr1 = [].slice.call(argumets); // [1, 2, 3]
console.log(arr1);
// ES6 的写法
let arr2 = Array.from(argumets); // [1, 2, 3]
console.log(arr2);
}
add(1, 2, 3);// 方法二:使用扩展运算符, 将伪数组转为真正的数组
// querySelectorAll()方法返回的是一个类似数组的对象
let lis = document.querySelectorAll('li');
console.log([...lis]);// Array.from()方法还可以接受第二个参数,对每个元素进行处理
let lis = document.querySelectorAll('li');
let names2 = Array.from(lis, s => s.textContent);
console.log(names2);
Array.of()
方法用于将一组值,转换为数组
// Array.of()方法用于将一组值,转换为数组
console.log(Array.of(3, 11, 20, [1, 2, 3], {id: 1}));
find() 方法:找出第一个符合条件的数组成员,它的参数是一个回调函数。
findIndex() 方法:找出第一个符合条件的数组成员的索引
let num = [1, 4, -5, 10, -4].find((n) => n < 0);
console.log(num); // -5let numIdex = [1, 4, -5, 10, -4].findIndex((n) => n < 0);
console.log(numIdex); // 2
ES6 提供三个新的方法——
entries()
,keys()
和values()
——用于遍历数组。它们都返回一个遍历器对象,可以用for...of
循环进行遍历,唯一的区别是:
keys()
是对键名的遍历、values()
是对键值的遍历,entries()
是对键值对的遍历
javascript">for (let index of ['a', 'b'].keys()) {console.log(index);
}
// 0
// 1for (let elem of ['a', 'b'].values()) {console.log(elem);
}
// 'a'
// 'b'for (let [index, elem] of ['a', 'b'].entries()) {console.log(index, elem);
}
// 0 "a"
// 1 "b"// 如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
includes() 返回一个布尔值,表示某个数组是否包含给定的值
注意:以前的 indexOf
方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,返回值是1或-1,所以要去比较是否不等于-1
,表达起来不够直观
console.log([1, 2, 3].includes(2)); // true
console.log([1, 2, 3].includes(4)); // false
Iterator遍历器
- 遍历器(Iterator)它是一种接口,为各种不同的数据结构提供统一的访问机制。
- Iterator 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令for…of循环,Iterator 接口主要供for…of消费。
- 原生具备 Iterator 接口的数据结构如下。
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
let items = ['one', 'two', 'three'];
//创建一个遍历器
let ite = items[Symbol.iterator]();
console.log(ite.next()) // { value: 'one', done: false }
console.log(ite.next()) // { value: 'two', done: false }
console.log(ite.next()) // { value: 'three', done: false }
console.log(ite.next()) // { value: undefined, done: true }
generator 生成器
使用场景:为不具备 Iterator 接口的对象提供了遍历操作
利用for…of循环,可以写出遍历任意对象(object)的方法。
原生的 JavaScript 对象没有遍历接口(不具备 Symbol.iterator方法),无法使用for…of循环,通过 Generator 函数为它加上这个接口,即将 Generator 函数加到对象的Symbol.iterator属性上面,就可以用了。
// Generator 生成器函数
function* objectEntries(obj){// 获取对象的所有 key 保存到数组 [name, age]const propKeys = Object.keys(obj);for(const propkey of propKeys){yield [propkey, obj[propkey]]}
}
const obj = {name: '牛肉粉',age: 18
}
// 把 Generator 生成器函数赋值给对象的Symbol.iterator属性, 为该对象加上遍历器接口
obj[Symbol.iterator] = objectEntries;
console.log(obj);
// objectEntries(obj) 等价于 obj[Symbol.iterator](obj)
for(let [key, value] of objectEntries(obj)){ console.log(`${key}: $value`);
}
对象
- 属性名与属性值同名可以省略
let name = '张三';let age = 18;let sex = '男';let obj = {name, //name:nameage,sex,// sayname:function(){// console.log(this.name);// }sayname(){console.log(this.name);}}obj.sayname();
- 属性名是变量 : []
let name='a'let obj={age:12,[name+'bc']:function(){console.log("aaa");}}console.log(obj);
方法
- 对象方法 is() === //比较两个值是否严格相等
console.log(NaN === NaN); //false (naa不等于任何数包括自己)console.log(Object.is(NaN,NaN)); //trueconsole.log( 0 === 0); //trueconsole.log(+0 === -0); //trueconsole.log(Object.is(+0,-0));//false
- 对象合并assign(target,obj1,obj2…) 浅拷贝
//对象的合并 assign(target,obj1,obj2....) 浅拷贝let newObj=Object.assign({},{a:1},{b:2})console.log(newObj);
解构赋值
// 解构赋值: 赋值运算的扩展,针对数组对象来进行操作,代码简洁易读let node={type:'div',name:'box',age:18,sex:'男'}// let {type,name,age,sex} = node;//完全解构let {type:mytype}=node//只解构typelet {type,...res}=node//只解构type,剩余的赋值给res(剩余运算符)// let {a=30,b}={b:20}//默认值let [a,[b],c]=[10,[20],30]//嵌套解构console.log(a,b);console.log(res);console.log(mytype);
ES6模块化
历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。
在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。
前者用于服务器,后者用于浏览器。
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
ES6 模块功能主要有两个命令构成:
export 和 import
export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量
//module/index.js
export const name = '张三';
export const age = 18;
export const sayName = function() {console.log(fristName);
}//也可以这样
const name = '张三';
const age = 18;
const sayName = function() {console.log(fristName);
}
export {name, age, sayName}
//main.js
import {name, age, sayName} from './modules/index.js';//解构赋值 {name, age, sayName}
使用export default
命令为模块指定默认输出,在其它模块加载该模块时,import
命令可以为该匿名函数指定任意名字
//export-default.js
export default function(){console.log('foo');
}//或者写成
function foo() {console.log('foo');
}export default foo;
//import-default.js
import customName from './export-default.js'
customNmae();//foo
如果想在一条import语句中,同时输入默认方法(default)和其他接口(非default),可以写成下面这样
//export-default.js
export default function(){console.log('foo');
}export function add(){console.log('add')
}
import customName,{add} from 'export-default.js'// 方式二 * 代表所有属性和方法 as 代表重命名
import * as f from 'export-default.js'
console.log(f); // 输出一个 模块, 里面保存了 export 传过来的所有属性和方法
console.log(f.default);
export default
也可以用来输出类。
// MyClass.js
export default class Person{ ... }// main.js
import Person from 'MyClass';
let o = new Person();