1、ES6
ES6是什么?ECMAScript6.0(ES6)是JavaScript语言下一代的标准,已经在2015年6月正式发布。它的目标是使得JavaScript语言可以编写复杂的大型应用。ECMAScript与JavaScript区别?ECMAScript是一种标准规范,JavaScript是ECMAScript的具体实现。ES6与ECMAScript2015的关系?ES6在2015年6月份正式发布,正式名称就是《ECMAScript2015标准》简称ES2015。ES6 == ECMAScript2015以后在每年的6月份将会发布一个新版本,将会已年份命名为版本号。(ES2016 ES2017)总结:ES6是一个历史名词,也是一个泛指,含义是5.1版本之后的JavaScript的下一代标准,涵盖了ES2015、
ES2016、ES2017等。而ES2015则是正式名称,特指该年发布的正式版本的语言标准。
2、Babel
Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,
以便能够运行在当前和旧版本的浏览器或其他环境中。babel无法转义一些API
babel默认只转义新标准引入的语法,比如ES6的箭头函数,不转移新的API,比如:iterator、Set、Map、Promise等全局对象。解决方法: 使用babel-polyfill 为当前环境提供一个垫片.npm install --save babel-polyfill
3、let const var
let const 是ES6中提出的变量声明let与const的特点一样。只不过let是用来声明变量的而const是用来声明常量的。var存在的问题:1.全局作用域2.存在变量提升3.可重复声明let const特点:1.局部作用域2.不可重复声明(同一作用域)3.没有变量提升const特性:1.使用const必须赋值。2.如果值是基本数据类型,则值不能改动。3.如果const声明的是对象类型,其保存的是对象的地址,const只能保证地址不发生改变,却不能保证该对象的值不发生改变。所以使用const时需要注意数值的类型。onConst() {//const a; //报错const a = 10;a = 100; //值不可改动}问题代码案列://使用var 定义的变量是全局变量,预期我们想要的是局部声明for (var i = 0; i < 10; i++) {}console.log(i); //10//重复声明 变量提升问题onStatement() {/*使用var定义 此处只会抛出undefined 而不是我们预期的报错JS实际上将代码声明提到了前面var b;console.log(b);b = 5;*/console.log(b); //undefinedvar b = 5;var b = 6; //重复声明不报错},//使用let解决重复声明 变量提升问题onStatementLet() {/** 无bable引入便会抛出异常Cannot access 'c' before initialization否则你将会看到和var等同的效果,bable会将es6的语法转换低级语法。let 没有变量提升let 无法重复声明变量 */console.log(c);let c = 5;//let c = 6; 报错}
4、Symbol数据类型
ES6之前JS存在的数据类型:NumberStringBooleanObjectNullUndefined转载:https://www.jianshu.com/p/f40a77bbd74e
5、解构赋值
//解构赋值let a, b, c;[a, b, c] = [1, 2];console.log(a, b, c); //1 2 undefined 未赋值将会赋值undefined[a, b, c] = [1, 2, 3];console.log(a, b, c); //1 2 3let d, arrys;[d, ...arrys] = [1, 2, 3, 4, 5];console.log(d, arrys); //1 [2, 3, 4, 5](...后将会已数组形式赋值)let q, w;[q, , w] = [1, 2, 3]; // ,占位符console.log(q, w); //1 3//解构赋值对象let t, y;({ t, y } = { t: 123, y: 456 });console.log({ t, y }); //{t: 123, y: 456}let num, total;({ k: num, j: total } = { k: 123, j: 456 });console.log({ num, total }); //{num: 123, total: 456}//模拟后台JSON数据 使用解构赋值simulationJson() {return {name: "司大屌",age: 23,hobby: ["篮球", "lol", "跑步"],computer: [{ name: "华硕" }, { name: "小米" }, { name: "苹果" }]};}, let dataJson = this.simulationJson();console.log(dataJson);let {name: JsonName,age: JsonAge,hobby: JsonHobby,computer: JsonComputer} = dataJson;//司大屌 23 ["篮球", "lol", "跑步"] [{…}, {…}, {…}]console.log(JsonName, JsonAge, JsonHobby, JsonComputer);let {name: JName,age: JAge,hobby: [JHobby], //只取出hobby数组第一个值computer: [{ name: JComputerName }] //只取出computer数组第一个对象的name值} = dataJson;//司大屌 23 篮球 华硕console.log(JName, JAge, JHobby, JComputerName);
6、ES6加强Unicode的缺陷
在ES5中JavaScript允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的unicode码点。
这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出必须用双字节形式表示,但是ES5无法正确识别双字节组成的字符,ES6可以。let a = "\u20bb7";console.log(a); //₻7 乱码let b = "\u{20bb7}";console.log(b); //𠮷 ES6中码点用{}包起来补充知识点:for-ofconsole.log(b.length); //2//传统for会将unicode字符识别乱码打印 � �for (let i = 0; i < b.length; i++) {console.log(b[i]);}//使用for of 会正确打印出数值 𠮷for (let w of b) {console.log(w);}//普通字符串 传统for 与 for-of 效果相同let bba = "1234567";for (let i = 0; i < bba.length; i++) {console.log("传统", bba[i]);}for (let w of bba) {console.log("for-of", w);}
7、ES6中新增字符串API和模板字符串
//ES6字符串APIlet str = "123Ldd321";//判断字符串是否包含指定字符串console.log("includes字符串包含", str.includes("Ldd")); //true//判断字符串的开头是否包含指定字符串,返回值是布尔值console.log("startsWith", str.startsWith("123")); //true//判断字符串的结尾是否包含指定字符串,返回值是布尔值console.log("endsWith", str.endsWith("123")); //false//repeat 将一个字符串重复n次str = str.repeat(3);console.log(str); //123Ldd321123Ldd321123Ldd321let b = "大屌";//padStart 在字符串开头已指定的字符补全 3代表补全后字符串的长度 "司"指定字符串b = b.padStart(3, "司");console.log(b); //司大屌//如果补全后的字符串长度小于补全前的 将不会执行b = b.padStart(1, "司");console.log(b); //司大屌//padEnd 在字符串后面补全b = b.padEnd(5, "游戏");console.log(b); //司大屌游戏
let name = "司大屌";let str = `我叫${name},今年${this.onReturnAge()} 反引号使用转义符 \``;console.log(str);//我叫司大屌,今年23 反引号使用转义符 `onReturnAge() {return 23;},注意:1.在模板字符串中使用反引号需要用到转义符2.在模板字符串中所有的空格和缩进符将会被保存输出3.在模板字符串中使用变量,必须${变量名}方式引入4.在模板字符串中${...}大括号中可以放入任意的JavaScript表达式
8、ES6数组操作
//数组扩展运算符使用//1.浅拷贝(复制数组)let list = [1, 2, 3, 4];let list2 = [...list];console.log(list2); //[1, 2, 3, 4]//2.分割数组let baseList = [1, 2, 3, 4];let [, ...newList] = baseList; //,占位符跳过第一个数据console.log(newList); //[2, 3, 4]//3.方法传参let addList = [1, 2];console.log(this.addTwoData(...addList)); //3addTwoData(x, y) {return x + y;},//fill 填充数据 数组是引用类型let fillList = [1, 2, 3, 4, 5];let fillList2 = fillList.fill(3); //将数组中所有的元素替换成3console.log(fillList == fillList2); //true fill改变原数组的值 只不过将地址复制。可参考下面浅拷贝console.log(fillList2); // [3, 3, 3, 3, 3]let fillListT = [1, 2, 3, 4, 5];let fillList3 = fillListT.fill(3, 1, 4); // 3 需要替换的值 1起始下标(包含) 4结束下标(不包含)console.log(fillList3); //[1, 3, 3, 3, 5]//浅拷贝使用fill 不会改变baseListFilllet baseListFill = [1, 2, 3, 4];let baseListFill2 = [...baseListFill].fill(2);console.log(baseListFill); //[1, 2, 3, 4]console.log(baseListFill2); //[2, 2, 2, 2]
//find findIndexconst list = [{ name: "张三", id: 1 },{ name: "李四", id: 2 },{ name: "王五", id: 3 },{ name: "张三", id: 4 }];//注意find 会找到首先找到第一个let listF = list.find(function(item) {return item.name === "张三";});console.log(listF); //{name: "张三", id: 1}let listFIndex = list.findIndex(function(item) {return item.name === "张三";});console.log(listFIndex); //0 返回下标//includes只能检测基本数据类型返回boolean 比indexOf 方便const bList = [1, 2, 3, 4, 5];let iB = bList.includes(2);console.log(iB); //true//flat 展开内嵌数据let flatList = [1, 2, 3, ["司大屌", 4, 5, ["欧文", 5, 6]]];//flat 默认展开1层 可以输入参数 指定展开层数let nList = flatList.flat(2);console.log(nList); // [1, 2, 3, "司大屌", 4, 5, "欧文", 5, 6]//Array.from() 将字符串转换为数组let str = "我家住在黄土高坡";let strList = Array.from(str);//["我", "家", "住", "在", "黄", "土", "高", "坡"]console.log(strList);console.log(typeof strList); //object
//数组 map函数使用let itemList = [{name: "vue",status: 1},{name: "java",status: 0},{name: "Spring",status: 1}];//map函数可以处理数组特定对象let newItemList = itemList.map(function(item) {let obj = {};//浅复制Object.assign(obj, item);obj.status = obj.status ? "已开课" : "未开课";return obj;});console.log(itemList); //0: {name: "vue", status: 1} 1: {name: "java", status: 0} 2: {name: "Spring", status: 1}console.log(newItemList); //0: {name: "vue", status: "已开课"} 1: {name: "java", status: "未开课"} 2: {name: "Spring", status: "已开课"}//数组 reduce使用//array.reduce(function(total, currentValue, currentIndex, arr), initialValue)/* total 必需初始值 initialValue若为空 total 为数组第一个元素 currentValue 必需当前元素 currentIndex 可选。当前元素的索引 arr 可选。当前元素所属的数组对象。 initialValue 可选。传递给函数的初始值*/let str = "abdhsdancsaa";let strList = Array.from(str);let obj = strList.reduce(function(total, value) {total[value] ? total[value]++ : (total[value] = 1);return total;}, {});console.log(obj);
9、ES6 和ES8对象新特性和API
//ES6和ES8对象新特性及新增方法//1.复制对象//注意:...复制对象是浅拷贝let obj = { name: "李某人", age: 23, hobby: { name: "hobby" } };let obj2 = { ...obj };obj.name = "司某人";obj.hobby.name = "篮球";console.log(obj == obj2); //false//注意 如果拷贝对象中存在对象,那么该字段将会存储的该对象的指针console.log(obj2); //{name: "李某人",age: 23,hobby: {name: "篮球"}}//2.设置默认值let sObj = { name: "李某人", age: 23 };let snObj = { ...sObj, name: "詹姆斯" };console.log(snObj); //{name: "詹姆斯", age: 23}//3.合并对象let sobj1 = { name: "欧文" };let sobj2 = { name: "科温顿", age: 23 };let sobj3 = { ...sobj1, ...sobj2 };let sobj4 = { ...sobj2, ...sobj1 };console.log(sobj3); //{name: "科温顿", age: 23}console.log(sobj4); //{name: "欧文", age: 23}//es5 书写对象 与 es6书写对象let name = "张三";let age = 23;let es5Obj = {name: name,age: age,sayHello: function() {console.log("es5--->Hello");}};//ES6更加直观let es6Obj = {name,age,sayHello() {console.log("es6--->Hello");}};es5Obj.sayHello();es6Obj.sayHello();//可计算的属性名let wName = "userName";//ES5写法let es5O = {};es5O[wName] = "王尼玛";//ES6初始对象写法let es6O = {[wName]: "司大雕"};console.log(es5O); //{userName: "王尼玛"}console.log(es6O); //{userName: "司大雕"}
// Object.is 判断两个值相等console.log(Object.is(NaN, NaN)); //trueconsole.log(NaN === NaN); //falseconsole.log(+0 === -0); //trueconsole.log(Object.is(+0, -0)); //falseconsole.log({} === {}); //falseconsole.log(Object.is({}, {})); //false// Object.assign 拷贝对象 也是浅拷贝 与 ... 存在同样问题 拷贝对象中内嵌对象属性let obj = { name: "张三", age: 23 };let obj2 = {};//obj2 目标对象 obj 来源对象Object.assign(obj2, obj);console.log(Object.is(obj, obj2)); //falseconsole.log(obj2); //{name: "张三", age: 23}//获取对象key value entrie//Object.keys() Object.values() Object.entries()let objK = { name: "王尼玛", age: 23, hobby: "睡觉" };console.log(Object.keys(objK)); // ["name", "age", "hobby"]console.log(Object.values(objK)); // ["王尼玛", 23, "睡觉"]console.log(Object.entries(objK)); //[Array(2), Array(2), Array(2)]//使用keys 循环复制对象let nObjK = {};for (let item of Object.keys(objK)) {nObjK[item] = objK[item];}console.log(nObjK); //{name: "王尼玛", age: 23, hobby: "睡觉"}
10、Map与WeakMap结构的特点
JavaScript对象实质就是键值对的集合(Hash结构),但在对象里却只能用字符串作为
键名。在一些特殊的场景中满足不了业务需求,因此, Map这一数据对象提出。Map对象:用于保存键值对,任何值。(对象或原始值都可以作为一个键名或一个值)WeakMap:1、只接受引用对象作为键名。2、没有clear 没有size 无法遍历
//Map对象使用//1let mapObj = new Map();mapObj.set([1, 2, 3], "科比");console.log(mapObj);//2new对象是初始化值//new Map([[key,value],[key,value],[key,value].....])let mapObj2 = new Map([["name", "司大屌"],["age", 23]]);console.log(mapObj2);console.log(mapObj2.get("name")); //司大屌//has 检测是否存在keyconsole.log(mapObj2.has("name")); //true//deletemapObj2.delete("name");console.log(mapObj2);//mapObj2.keys() mapObj2.values() mapObj2.entries()//默认遍历 mapObj2.entries()for (let item of mapObj2) {console.log(item);}
11、Set与WeakSet结构特点
Set是ES6提供的一种类似数组的数据结构,可以理解为集合。它和数组最大的区别就是:它的值不会重复。WeakSet:1.数组成员必须是对象。2.无法遍历 不存在keys() values() entries() forEach()等方式和size属性
let setObj = new Set();setObj.add(1).add(2);console.log(setObj);let setObj2 = new Set([1, 2, 3, 4, 5]);console.log(setObj2);setObj2.delete(2);console.log(setObj2);//setObj2.keys() setObj2.values() setObj2.entries()//setObj2.keys() setObj2.values () 遍历的值相同//默认遍历的是 setObj2.values()for (let key of setObj2.keys()) {console.log(key);}
12、Map、Set与Array及Object区别
// 判断对象中是否包含某个属性let obj = {name};obj["name"] = "李某人";//判断某个属性是否存在let checkIs = "name" in obj;let checkIs2 = "age" in obj;console.log("check", checkIs, checkIs2); //check true false//删除对象中某个属性delete obj.name;console.log(obj); //{}//类型转换//1 对象转换maplet obj1 = {name: "李某人",age: 23};let map = new Map(Object.entries(obj1));console.log(map);//2 map转换对象let obj2 = Object.fromEntries(map);console.log(obj2);//3 数组转换setlet array = [1, 2, 3, 4];let set = new Set(array);console.log(set);//4 set转换数组let arrsy2 = Array.from(set);console.log(arrsy2);
13、ES6中Proxy与Reflect
//Proxy ES6引入操作对象API 代理对象的读取 设置等操作let obj = {name: "李明明",age: 23,phone: "18700185678"};//第一个参数 用于代理的目标对象//第二个参数 一个对象,对代理对象进行拦截操作的函数let objProxy = new Proxy(obj, {//target 当前目标对象//key 目标对象属性名get: function(target, key) {switch (key) {case "phone":return target[key].substr(0, 3) + "****" + target[key].substr(7);default:return target[key];}},set: function(target, key, value) {switch (key) {case "name":return (target[key] = value + "代理名称");default:return target[key];}},// in操作has: function(target, key) {if (key in target) {console.log("属性存在");} else {console.log("属性不存在");}},//deletedeleteProperty: function(target, key) {if (Object.is(key, "name")) {console.log("name属性无法删除");} else {delete target[key];}}});console.log(objProxy.phone); //187****5678objProxy.name = "司大屌";console.log(objProxy.name); //司大屌代理名称"name" in objProxy; //属性存在//delete objProxy["name"]; //name属性无法删除/*** Reflect* ES6引入Reflect也是用来操作对象的,它将对象里一些明显属于语言* 内部方法移植到Reflect对象中,它对某些方法返回结果进行了修改,* 使其更合理,并且使用函数方法实现了Object命令式操作** */let objR = {name: "李某人",age: 23};//以后操作对象尽量都使用Reflect对象//获取属性值console.log(Reflect.get(objR, "name")); //李某人//修改属性值Reflect.set(objR, "name", "詹姆斯");console.log(objR.name); //詹姆斯//检测属性名是否存在console.log(Reflect.has(objR, "name")); //true
14、ES6函数扩展
//ES6函数扩展//1 函数默认参数function seyHello(x, y = "world") {console.log(x + y);}seyHello("hello"); //helloworldseyHello("你好", "世界"); //你好世界//2 可变参数function sumAdd(...v) {let num = 0;for (let p of v) {num += p;}console.log("num", num);}sumAdd(1, 2, 3, 4, 5);
15、箭头函数
//箭头函数//声明函数const arrow = (x) => {console.log("我是箭头函数", x);};//调用arrow(100); //我是箭头函数 100//如果箭头函数参数只有一个可以省略() 如果返回只有一条语句可以省略{}const arrow2 = x => x * 2;console.log(arrow2(2)); //4
16、ES6类
//ES5 使用构造函数来实现类的功能function Person(name, age) {this.name = name;this.age = age;}Person.prototype.sayHello = () => {console.log(`我叫${this.name},今年${age}`);};let p = new Person("张三", 23);console.log(p); //Person {name: "张三", age: 23}//ES6实现类的方法class PersonES6 {constructor(name, age) {this.name = name;this.age = age;}sayHello() {console.log(`我叫${this.name},今年${this.age} 再也不给xx借钱`);}}let p1 = new PersonES6("李某人", 22);console.log(p1);p1.sayHello(); //我叫李某人,今年22 再也不给xx借钱//ES6类继承class A {constructor(name, age) {this.name = name;this.age = age;}}class B extends A {}class C extends A {constructor(name, age) {//子类构造函数中super放到第一行super(name, age);this.name = name;this.age = age;}// get set 方法get getName() {return this.name;}set setName(value) {this.name = value;}//静态方法static sayHelloS() {console.log("我是静态方法");}}let cP = new C("李默", 22);console.log(cP); // {name: "李默", age: 22}console.log(cP.name); //李默console.log(cP.getName); //李默cP.setName = "张三";console.log(cP); // {name: "张三", age: 22}console.log(cP.name); //张三console.log(cP.getName); //张三//调用类的静态方法C.sayHelloS(); //我是静态方法
17、import export
方式1//JSFile1.jsexport let a = 10;export function sayHello() {console.log("hello");
}//方式1
import { a, sayHello } from "../utils/jsFile1";
//引入全部 取个别名
import * as oneAll from "../utils/jsFile1";方式2 推荐这种方式
//jsFile2let a = 10;function sayHello() {console.log("hello");
}export default {a,sayHello
}import two from "../utils/jsFile2";console.log(two.a);
two.sayHello();
18、Promise
//promise//1.主要用于异步计算//2.可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果//3.可以在对象之间传递和操作promise,帮助我们处理队列//then() 调用的就是resolve()//catch() 调用的就是reject() function ajax(num) {//resolve 成功时执行下一步操作//reject 失败时执行的下一步操作return new Promise((resolve, reject) => {if (Object.is(num, 200)) {resolve();} else {reject();}});}ajax(200).then(() => {console.log("成功");}).catch(() => {console.log("失败");});//模拟多层异步回调使用function ajaxAsyn() {return new Promise((resolve, reject) => {setTimeout(() => resolve(), 1000);});}ajaxAsyn().then(() => {console.log("任务进度1执行完成");return new Promise((resolve, reject) => {setTimeout(() => resolve(), 1000);});}).then(() => {console.log("任务进度2执行完成");});
19、iterator
/*** iterator遍历器是一种接口,目的是为了给不同的数据结构提供统一的循环方式,* 任何数结构如果部署了iterator接口,就能够实现遍历的操作。** 原生具有iterator接口** Array* String* Set* Map* 函数的argument对象** */let arrsy = [1, 2, 3, 4, 5];let iterator = arrsy[Symbol.iterator]();// 使用for of// for (const it of iterator) {// console.log(it); // 1 2 3 4 5// }//使用 iterator.next() 迭代let s = iterator.next();while (!s.done) {console.log(s.value);s = iterator.next();}
20、async
async:async是异步简写,用于声明一个函数是异步函数.awati:等待的是一个表达式,这个表达式的计算结果是Promise对象或者其他值.function fn1() {setTimeout(() => console.log("任务1"), 1000);}function fn2() {setTimeout(() => console.log("任务2"), 1000);}function fn3() {setTimeout(() => console.log("任务3"), 1000);}function init() {fn1();fn2();fn3();}/*** 任务1 任务2 任务3 在等待1秒后同时输出了* 若想实现 任务1 输出后 等待1秒输出任务2 任务2输出后等待1秒输出任务3* 使用async 结合 Promise**/init();//使用async Promise改进function pn1() {return new Promise(resolve => {setTimeout(() => {console.log("异步任务1");resolve();}, 1000);});}function pn2() {return new Promise(resolve => {setTimeout(() => {console.log("异步任务2");resolve();}, 1000);});}function pn3() {return new Promise(resolve => {setTimeout(() => {console.log("异步任务3");resolve();}, 1000);});}async function initP() {//await 会等待 Promise 中 resolve() 或 reject() 调用后执行//new Promise 中若没有调用.then() 或者.catch() 默认是传入的空函数,方法体中代码在返回对象时执行await pn1().then(() => {console.log("结束");});await pn2();await pn3();}initP();
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】 进行投诉反馈!