ES6 是对javascript语言的一次重大升级,目前es6中很多新语法和特性已经被浏览器兼容,还有一些新语法可以借助插件实现浏览器兼容。
总之现在就开始用es6编写javascript绝对是趋势...这里记录一些es6中常用的新特性和其引用场景。
1.新的数据类型Symbol,新的数据结构(对象)Set,Map
1.1 Symbol数据类型
Symbol和string,bool一样,是一种新增的基础类型数据,代表一个唯一的不可重复的数值
let s1 = Symbol(1); //内部参数为描述
console.log(s1,typeof s1); //Symbol(1) "symbol"
console.log(Symbol(2) == Symbol(2)); //false (唯一性)
console.log(String(Symbol(1))); //"Symbol(1)" (可以转为字符串类型)
console.log(!Symbol(1)); //false (可转为bool类型)
//不能转为数字类型,不能使用运算符进行运算
1.2 Set对象
Set类似于数组,但是成员的值都是唯一的,没有重复的值。可以应用Set做数组去重
const s = new Set([1,2,3]);
s.size = 3;
s.add("a").add("b"); console.log(s); //Set {1, 2, 3, "a", "b"}
s.delete("a"); console.log(s.has("a")); //false
const arr2 = [1,2,'a','b',2,'a'];
console.log([...new Set(arr2)]); //[1,2,'a','b'] 数组去重
1.3 Map对象
Map类似json对象,但是不能像json那样设置,获取,删除属性和值
var map = new Map(); //创建Map数据
map.set(name,value); //设置键和值
map.get(name); //获取值
map.delete(name); //删除值
Map数据只能通过for of遍历
2.字符串,数组,对象,函数的扩展
2.1字符串的扩展
//repeat()重复操作
let str1 = 'a';
let str2 = str1.repeat(3); // "aaa"
//includes() 判断是否包含段字符
let str = 'abcf';
console.log(str.includes('cf')); //true
console.log(str.includes('cd')); //true
//startsWith() 判断是否以某个字符开头
console.log(str.startsWith('ab')); //true
console.log(str.startsWith('b')); //flase
//endsWidth() 判断是否以某个字符结尾
console.log(str.endsWith('cf')); //true
console.log(str.endsWith('c')); //flase
2.2数组的扩展
//Array.from() 将类数组转为数组
var aAs = document.querySelectorAll("a");
var aArr = Array.from(aAs); //aArr为数组,存的是dom对象
//Array.of(); 创建数组
var arr1 = Array.of(1,'a',2,3,3);
//find(val,eq,arr) 找出第一个符合条件的数组成员
//findIndex(val,eq,arr) 找出第一个符合条件的数组成员的索引
//三个参数,依次为当前的值、当前的位置和原数组
var arr2 = ['a',2,'c',11,4];
let res1 = arr2.find(function(val,eq,arr){
return val < 4;
});
let res2 = arr2.findIndex(function(val,eq,arr){
return val > 2 && val <10;
});
console.log(res1); //2
console.log(res2); //4
//fill() 数组填充,覆盖
var oarr = [1,2,3];
//oarr.fill("a"); console.log(oarr); // ["a", "a", "a"]
oarr.fill("a",1,2); console.log(oarr); // [1, "a", 3]
//map()映射方法.n个值,n个结果
var arr = [61,20,70];
var arr2 = arr.map(function(item){
return item>=60?'及格':'不及格';
});
//arr2 //['及格','不及格','及格']
//reduce()方法.n个值,1个结果
var arrr1 = [68,53,12];
var res = arrr1.reduce(function(tmp,item,index){ //求和
return tmp+item; //返回前两个数的和,然后继续执行,直到返回一个值.index为执行索引
});
//res //133
//filter() 过滤方法
var res2 = arrr1.filter(function(item){ //过滤掉奇数
if(item%2==1){
return false; //奇数不要
}else{
return true;
}
});
//forEach() 遍历方法
arrr1.forEach(function(item,index){
console.log(`第${index}个是${item}`); //第0个是68
});
2.3对象的扩展
//Object.is() 判断数据形式是否一样
console.log(NaN === NaN); //false
console.log(Object.is(NaN,NaN)); //true
console.log(+0 === -0); //true
console.log(Object.is(+0,-0)); //false
//Object.assign() 对象的合并
var obj1 = {a:1}
var obj2 = {a:2,b:3}
var obj3 = {c:'abc'}
Object.assign(obj1,obj2,obj3); //obj1为源对象
console.log(obj1); // Object {a: 2, b: 3, c: "abc"}
//stringify() //json转字符串
//pares() //字符串转json
2.4函数的扩展
//函数的rest参数
function fn(...args){ //...可以展开数组和json,此处...args等于[]
args.push(4);
console.log(args);
}
fn(1,2,3); //[1,2,3,4]
var json1 = {a:"a1",b:"b1"}
var json2 = {...json1,c:"c1"} //{a: "a1", b: "b1", c: "c1"}
//箭头函数
//原则:1.函数有且只有一个参数,()可以不写. 2.函数有且只有一个语句,且是return语句,{}可以不写.
const fn = (a,b) => a+b; //箭头后跟变量,指函数返回值
const fn2 = function(a,b){ //fn2与fn效果一样
return a+b;
}
const fn = a =>{ const b=a+1;return b } //箭头函数后跟{},不再是返回值,而是函数体
fn(1); //2
const fn2 = (a,b) =>({a,b}); //要返回函数体时,用()包裹,返回的是一个对象
fn2(1,2); //Object {a: 1, b: 2}
h => h(App) //等价于 h => { return h(App) } //也等价于function (h) { return h(App) }
//箭头函数体内没有自己的this,在使用时,内部的this就是定义时所在环境的对象.
document.onclick = ()=>{
console.log("ok");
console.log(this===window); //true,此处this不再指向触发方法的对象
}
3.解构赋值,字符串模板,扩展运算符
3.1解构赋值
原则:等号两边的结构必须一样,需要一个等式同时完成.
简单的场景: var [a,b,c] = [1,2,3]; a为1,b为2..
在得到json数据时也可以直接解构赋值:
var data = {"title":"a","msg":"aa"};
var {title,msg,name="默认名"} = data;
//title为"a",msg为"aa",name为"默认名"
函数传参时可以传入默认值:
function fn({name="lili"}={}){
console.log(name); //输出lili
}
function fn(name="lili"){
console.log(name); //输出lili
}
3.2字符串模板字符串连接
let flag = true;
let str = "上海";
let html = `<ul>
<li>${'首页'}</li>
<li>${str}</li>
<li>${flag?'北京':'上海'}</li>
</ul>`;
console.log(html); // <ul><li>首页</li><li>上海</li><li>北京</li></ul>
3.3 扩展运算符
扩展运算符...可用作数组复制,常用的数组复制方式有:Array.from()方法;连接空数组
var arr1 = [1,2];
//var arr2 = Array.from(arr1);
//var arr2 = arr1.concat([]);
var arr2 = [...arr1];
arr2.push(3); console.log(arr2); //[1,2,3] //arr1 [1,2]
4.for-of循环和iterator
4.1 for-of主要用来循环Map数据,还可以循环数组,不能循环json
var arr = ['a','b','c'];
for(var i in arr){
console.log(i); // 0,1,2
}
for(var i of arr){
console.log(i); // a,b,c
}
var map = new Map();
map.set("a","11");
map.set("b","22");
for(var name of map){
console.log(name); //同时输出键和值 a,11 ; b,22
}
for(var [a,b] of map.entries()){ //此处map.entries()就是map的默认值
console.log(a,b); // a 11; b 22
}
for(var key of map.keys()){ //仅遍历键
console.log(key); // a;b
}
for(var val of map.values()){ //仅遍历值
console.log(val); // 11;22
}
4.2 iterator方法
var arr = [1,2,3];
var itArr = arr[Symbol.iterator](); //原生方法运行后得到该数据的对象指针
//数组,set,map都有对应各自类型的对象指针,json不具备
console.log(itArr.next()); //{value: 1, done: false}
console.log(itArr.next()); //{value: 2, done: false}
console.log(itArr.next()); //{value: 3, done: false}
console.log(itArr.next()); //{value: undefined, done: true}
//具备iterator方法的数据结构都可以进行解构赋值和扩展运算符
5.es6中的面向对象与继承
5.1面向对象
es5中面向对象是通过new构造函数实现的,es6中有了class
class Person{ //类
constructor(name="小明"){
this.name = name
}
showName(){
console.log(this.name)
}
}
var p1 = new Person("lili");
p1.showName();
5.2对象继承
在es5中,对象的继承分为属性继承和方法继承.属性通过call/apply原型冒充来继承,方法通过原型对象来继承.es6中可以通过extends来继承了
class Person{ //类
constructor(name="小明"){
this.name = name;
this.head = 1;
}
static showClass(){ //静态方法
console.log("人类");
}
showName(){
console.log(this.name)
}
}
class Worker extends Person{
}
var p1 = new Person();
var w1 = new Worker("工人小王");
p1.showName===w1.showName; //true, 子类和父类的实例的方法都是一个引用地址
Person.showClass(); //人类, 通过extend继承
Worker.showClass() //人类, 子类继承了父类的属性,方法,静态方法
若子类中还需定义其他属性时,需要先继承父类的构造器中的属性:
class Worker extends Person{
constructor(name){
//this.name ="xxx"; //找不到this,子类必须先调用super,才能用this
super(name); //继承父类构造器中的属性,类似es5中的call/apply
this.name ="xxx"; //子类可以覆盖或新增新的属性
}
}
6.es6中的模块化
6.1 export/import实现模块化
早期实现模块化都有sea,require。目前es6中支持export/import的方式实现模块化。目前浏览器对模块化的兼容还不完善,可以用构建工具开发并引入babel等方式实现。
模块文件的创建和引入
//=================export=======================
//a.js 一个js文件中,多个export语句导出多个模块
export const a ="dd"
export const b ="ee"
//b.js 引入a.js
//import {a} from 'a.js' //引入模块需要写在{}中
//import {a,b} from 'a.js' //引入时变量名需要对应
import * as objs from 'a.js' //将a.js内所有导出的模块集成为一个对象objs
//=================export default================
//c.js 导出一个模块,一个文件中只能有一个export default语句
export default 'hello world'
//d.js 引入c.js
import a from 'c.js' //引入export default导出的模块时,变量名不用对应
//-----------------------------------------------------------
//e.js 用export default语句导出多个模块
const str = 'hello world';
const txt = '你好';
export default {str,txt}
//f.js 引入e.js
import a from './e.js'
console.log(a.str,b.txt) //hello world 你好
6.2 CommonJs模块化 (node中采用的是CommonJs规范)
//a.js 导出模块
const str = 'hello world';
module.exports = str;
//b.js 引入模块
const b = require('./a.js');
console.log(b); //hello world
7.es6中的Promise
Promise是一个对象,可以通过new来创建实例。有两个原型方法和几个静态方法。
7.1 then,catch方法
const p = new Promise(function(resolve,reject){
const img = new Image();
img.src = "https://resource.hbiger.com/image/blog/archive/flex/5.jpg";
img.onload = function(){
resolve(this);
}
img.onerror = function(err){
reject(err);
}
});
//异步响应,等图片加载动作完成后执行
p.then(function(img){
document.body.appendChild(img)
},function(err){
})
//或者用catch方法替换上面第二个参数
p.then(function(img){
document.body.appendChild(img)
}).catch(function(err){
})
7.2 all,race等静态方法
var p2 = Promise.resolve(3); //创建一个成功的响应
var p3 = Promise.reject(5); //创建一个失败的响应
//all静态方法,当页面渲染需要等待多个异步数据都完成后才能进行时,使用all
Promise.all([p1,p2,p3]).then(function(datas){
console.log(datas); //当p1,p2,p3三个响应都成功时才执行then
},function(err){ ///... }) //p1,p2,p3中有一个不成功,便执行err,返回错误信息
//race静态方法,当页面同时发出多个异步请求,使用响应最快的请求的返回数据时,可以用到race
var t1 = new Promise(function(resolve,reject){
setTimeout(resolve,500,'one'); //延迟执行resolve('one');
});
var t2 = new Promise(function(resolve,reject){
setTimeout(resolve,300,'two');
});
Promise.race([t1,t2]).then(function(value){
console.log(value); //two
});
8.async,await
8.1 await会在async异步函数内阻塞当前线程向后执行
//假设promiseFun是一个异步方法
function promiseFun(){
return new Promise((resolve,reject)=>{
new Promise((resolve,reject)=>{
resolve()
})
.then(()=>{
resolve()
console.log('innerPromise')
})
})
}
async function fn(){
let a = await promiseFun();
console.log('fn')
console.log(a)
}
fn();
//打印innerPromise
//打印fn
//打印promiseFun
//返回一个Promise {: undefined}
8.2 await并不是阻塞主线程执行,因为async函数本身是异步的,所以await其实是阻塞的当前异步函数的异步线程
var hold = function () {
return new Promise(function (resolve, reject) {
resolve();
})
};
async function count(i){
await hold()
console.log(i)
}
for(var i = 0 ;i < 3 ; i++){
count(i);
}
console.log("run")
//打印run
//打印0
//打印1
//打印2
1.虽然await会阻塞async异步函数,但是并没有阻塞主线程。
2.虽然await阻塞异步函数向后执行,看起来像是同步的,但是它本质还是异步的,我们同样可以并行执行。而同步函数不能并行执行。
9.proxy代理器,对目标对象的操作进行代理
var oa = {a:"aa"}
const proxy = new Proxy(oa, {
get(target, key) {
// 这里的 target 就是 Proxy 的第一个参数对象
console.log('proxy get key', key)
return target[key]
},
set(target, key, value) {
target[key] = value
console.log('value', value)
}
})
proxy.a
//proxy get key a
proxy.a = "aa2"
//value aa2
//oa.a === "aa2" //true
Proxy支持拦截的操作,一共有13种:
1.get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。
2.set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
3.has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
4.deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
5.ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、6.Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
7.getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
8.defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
9.preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
10.getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。
11.isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
12.setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
13.apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
欢迎转载:转载时请注明本文出处及文章链接