简介
ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准
let const
声明变量的关键字
es6 之前使用var
es6 引入let const
特点
- 没有变量提升
不能在未声明之前使用- 形成块作用域
声明的变量只在当前它所在的代码块有效,可以使用- 不可重复声明
- 不污染全局变量
使用场景
js
// 作用1:for循环
const arr=[]
for(let i=0 ; i<9;i++)
{
arr[i]=function()
{
return i;
}
}
console.log(arr[5]()); //5
const 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); //10
console.log(window.RegExp); //fn
let RegExp=10;
console.log(window.RegExp); //fn
模板字符串
before:
js
box.innerHTML='<li>'+name+'</li>'
after:
用于字符串拼接,当拼接有变量存在的时候 ,更加方便
js
//模板字符串 ``,插入变量使用${},利于拼接字符串
const box=document.querySelector('.box')
const name='adefhb'
box.innerHTML=`
<ul>
<li>
<span>${name}</span>
</li>
</ul>
`
数据类型
map
键值对
- 增
set - 删
delete - 改
set - 查
get,has - 遍历
js
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
无重复值的列表
js
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 // 释放掉object
set2.delete(obj) // 可以释放掉了
console.log(set2);
//解决方法 WeakSet() --- 也释放不了
// let weakSet= new WeakSet()
// weakSet.add(obj)
// weakSet.add({})
// obj=null // 释放掉object
// console.log(weakSet);
symbol
js
//原始数据类型 , 代表的是独一无二的值
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
构造类
js
//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);
}
})
类的继承
js
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);
}
}
函数
函数参数默认值
js
//1.es5 带参数默认值的函数
function add(a,b){
a=a||10
b=b||20
console.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 伪数组,函数内部使用,收集函数参数
js
//es5
let 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);
扩展运算符
- ... 分割数组,对象,将各个项作为分离的参数传给函数
js
//eg:求数组的最大值
const arr=[10,20,50,100,30,40,50]
//1.使用apply
console.log(Math.max.apply(null,arr));
//2.使用扩展运算符
console.log(Math.max(...arr));
箭头函数
this 指向问题
es5
js
//this 指向函数的调用者
let PageHandle={
id:123,
init:function(){
document.addEventListener('click',function(){
console.log(this); // document
this.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); // document
this.doSomethings(); //TypeError: this.doSomethings is not a function
}.bind(this))
},
doSomethings:function(){
console.log("我被调用了");
}
}
PageHandle.init();
es6
箭头函数 没有this指向:当前作用域没有this,从上级作用域链中寻找
js
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.不能使用arguments
let add=(a,b)=>{
console.log(arguments);
}
add(1,2,3); //ReferenceError: arguments is not defined
数组扩展方法
Array.from()
方法用于将伪数组转为真正的数组
js
// 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()
方法用于将一组值,转换为数组
js
// Array.of()方法用于将一组值,转换为数组
console.log(Array.of(3, 11, 20, [1, 2, 3], {id: 1}));
find() 方法:找出第一个符合条件的数组成员,它的参数是一个回调函数。
findIndex() 方法:找出第一个符合条件的数组成员的索引
js
let num = [1, 4, -5, 10, -4].find((n) => n < 0);
console.log(num); // -5
let 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
// 1
for (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
,表达起来不够直观
js
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 对象
js
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属性上面,就可以用了。
js
// 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`);
}
对象
- 属性名与属性值同名可以省略
js
let name = '张三';
let age = 18;
let sex = '男';
let obj = {
name, //name:name
age,
sex,
// sayname:function(){
// console.log(this.name);
// }
sayname(){
console.log(this.name);
}
}
obj.sayname();
- 属性名是变量 : []
js
let name='a'
let obj={
age:12,
[name+'bc']:function(){
console.log("aaa");
}
}
console.log(obj);
方法
- 对象方法 is() === //比较两个值是否严格相等
js
console.log(NaN === NaN); //false (naa不等于任何数包括自己)
console.log(Object.is(NaN,NaN)); //true
console.log( 0 === 0); //true
console.log(+0 === -0); //true
console.log(Object.is(+0,-0));//false
- 对象合并assign(target,obj1,obj2...) 浅拷贝
js
//对象的合并 assign(target,obj1,obj2....) 浅拷贝
let newObj=Object.assign({},{a:1},{b:2})
console.log(newObj);
解构赋值
js
// 解构赋值: 赋值运算的扩展,针对数组对象来进行操作,代码简洁易读
let node={
type:'div',
name:'box',
age:18,
sex:'男'
}
// let {type,name,age,sex} = node;//完全解构
let {type:mytype}=node//只解构type
let {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关键字输出该变量
js
//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}
js
//main.js
import {name, age, sayName} from './modules/index.js';//解构赋值 {name, age, sayName}
使用export default
命令为模块指定默认输出,在其它模块加载该模块时,import
命令可以为该匿名函数指定任意名字
js
//export-default.js
export default function(){
console.log('foo');
}
//或者写成
function foo() {
console.log('foo');
}
export default foo;
js
//import-default.js
import customName from './export-default.js'
customNmae();//foo
如果想在一条import语句中,同时输入默认方法(default)和其他接口(非default),可以写成下面这样
js
//export-default.js
export default function(){
console.log('foo');
}
export function add(){
console.log('add')
}
js
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
也可以用来输出类。
js
// MyClass.js
export default class Person{ ... }
// main.js
import Person from 'MyClass';
let o = new Person();