引言:
ES全称ECMAScript,ECMAScript是ECMA制定的标准化脚本语言。目前JavaScript使用的ECMAScript版本为ECMA-417。关于ECMA的最新资讯可以浏览 ECMA news。
为什么学习ES6+ ?
ES5发布近5年后才被标准化,ES6+新特性让开发更高效
前置知识:
- 熟悉ES5
- 了解ES6+
隐藏着黑暗力量的钥匙啊,在我面前显示你真正的力量!迷人又刷漆的大帅比 or 美丽又善良的xiao镁铝 ? 封印解除!!!durang~~
-
新的声明方式
ES6之前,JS是没有块级作用域的,const与let填补了这方便的空白,const与let都是块级作用域。
1. var:variable的简写,可理解成变量的意思。 2. let:英文中表示“让”,也是一种声明方式。 3. const:英文表示常量,ES6中用来声明常量,常量你可以简单理解为不变的量,类似Java中的枚举。
var a = 'awesome'; console.log(a); // awesome
var a = 'awesome' { var a = ‘cool’; } console.log(a); // 不会报错,且打印出cool
对比以上两段代码,得出以下结论:var在ES6存在变量提升特性。
var a = 'awesome'; { let a = 'cool'; } console.log(a); // awesome
{ let a = 'awesome'; } console.log(a); // Uncaught ReferenceError: a is not defined
let声明块级作用域
for(var i = 0; i < 10; i++){ console.log('循环体中:' + i); } console.log('循环体外:' + i);
for(let i = 0; i < 10; i++){ console.log('循环体中:' + i); } console.log('循环体外:' + i);
var返回结果:
let返回结果
结论:let在防止程序数据污染。for循环let声明,减少var声明污染全局空间
|
有些变量是希望声明后在业务层就不再发生变化,这时用const声明
-
变量的解构赋值
数组的解构赋值:
从前:
let a=0; let b=1; let c=2;
现在:
let [a, b, c]=[1,2,3]; let [a,[b, c],d]=[1,[2,3],4];
解构默认值:// --------------- foo = true ------------------------------------------------- let [foo = true] =[]; console.log(foo); // 控制台打印出true // ---------------- b="awesome" ------------------------------------------------ let [a, b="awesome"]=['大数据'] console.log(a+b); // 控制台显示“大数据awesome” // ----------------- undefined相当于没有定义了但是没有值,所以b取默认值。 -------------------------- let [a, b="awesome"]=['大数据',undefined]; console.log(a+b); // 控制台显示“大数据awesome” // ----------------- null相当于有值,但值为null。所以b并没有取默认值,而是解构成了null。 ------------------- let [a, b="awesome"]=['大数据',null]; console.log(a+b); // 控制台显示“大数据null”
对象解构赋值let {foo, bar} = {foo:'awesome',bar:'大数据'}; console.log(foo+bar); // 控制台打印出“awesome大数据” let json = { a:'jack', b:'马云' } function fun({a, b='syk'}){ console.log(a, b); } fun(json); // 输出jack 马云 ≈ 执行了 fun({a, b='syk'} = {a:'jack', b:'马云'}})
PS:对象的解构与数组解构不同:
a. 数组的元素是按次序排列,变量的取值由位置决定;
b. 对象的属性没有次序,变量须与属性同名,才可取到正确的值。
圆括号的使用
let foo; {foo} ={foo:'awesome'}; console.log(foo);
解构之前定义变量,解构会出现问题。
解决方案 —— 外部加圆括号
let foo; ({foo} ={foo:'awesome'}); console.log(foo); //控制台输出awesome
字符串解构
const [a, b, c, d, e, f]="awesome"; console.log(a); console.log(b); console.log(c); console.log(d); console.log(e); console.log(f);
-
扩展运算符和rest运算符
对象扩展运算符(…)
// 编写一个方法时,我们允许它传入的参数是不确定的: function myFunc(...arg){ console.log(arg[0]); console.log(arg[1]); console.log(arg[2]); console.log(arg[3]); } myFunc(1,2,3); // 数组构造或字符串: [...iterableObj, '4', ...'hello', 6]; // 构造对象时,进行克隆或者属性拷贝(ECMAScript 2018规范新增特性): let objClone = { ...obj };
rest运算符
// 编写一个方法时,我们允许它传入的参数是不确定的: function myFunc(first, ...arg){ console.log(arg.length); } myFunc(0,1,2,3,4,5,6,7); // 控制台输出7,说明arg中有7个元素
// 编写一个方法时,我们允许它传入的参数是不确定的: function myFunc(first, ...arg){ for(let val of arg){ console.log(val); } } myFunc(0,1,2,3,4,5,6,7); // 控制台输出1 2 3 4 5 6 7
-
字符串模版
// ----------------------- 拼接字符串 ----------------------------- const [first, last0 = ['curry','james'] // 不使用模板字符串 let name = 'Your name is ' + first + ' ' + last + '.' // 使用模板字符串 let name = `Your name is ${first} ${last}.` // 外层用反引号 // ----------------------- 字符串查找 ----------------------------- // ES5写法 const jj = '林俊杰'; const news = '2019年8月20日,林俊杰来到上海趣头条大数据部,与大数据部同学们一起研究ES6...' console.log(news.indexOf(jj)) // 返回11,需要在条件中判断11是否大于-1,来查找字符串 ES6写法: console.log(news.includes(jj)) // 返回true // ----------------------- 字符串复制 ----------------------------- console.log('stephen'.repeat(3)) // 返回stephenstephenstephen 实际应用场景不多
-
数字
// ----------------------- Number.isFinite( ):数字验证,只要是数字,不论是浮点型还是整形都返回true,其返回false。 ----------------------------- let a = 11/4; console.log(Number.isFinite(a)); // true console.log(Number.isFinite('jack')); // false console.log(Number.isFinite(NaN)); // false console.log(Number.isFinite(undefined)); // false // ----------------------- Number.isNaN( ):NaN是特殊的非数字,可以使用Number.isNaN()来进行验证 ----------------------------- console.log(Number.isNaN(NaN)); // true
-
数组
// ----------------------- Array.from():Json对象转数组 ----------------------------- let json = { '0': 'Sephirex', '1': '王思聪', '2': '国名老公', length:3 // 必要条件,对象中前几个属性须严格定义为0、1、2 字符串 } let arr=Array.from(json); console.log(arr) // ["Sephirex", "王思聪", "国名老公"] // ----------------------- Array.of() :文本或者变量转换成数组 ----------------------------- // --- 数字 let arr =Array.of(3,4,5,6); console.log(arr); // --- 字符 let arr =Array.of('王思聪','Sephirex','国名老公'); console.log(arr); // ----------------------- Array.find() :传入匿名函数,查找指定值 ----------------------------- let arr=[1,2,3,4,5,6,7,8,9]; console.log(arr.find(function(value, index, arr){ return value > 5; })) // 返回6,如果找不到会显示undefined // ----------------------- Array.fill() :填充数组 ---------------------------------------- let arr=[0,1,2,3,4,5,6,7,8,9]; arr.fill('james',2,5); // 接收三个参数,填充的变量,开始填充的位置,填充到的位置。 console.log(arr); // 输出 [0, 1, "james", "james", "james", 5, 6, 7, 8, 9] // ----------------------- for … of :遍历数组输出val or key --------------------------------------------- let arr=["Sephirex", "王思聪", "国名老公"]; for (let item of arr){ console.log(item); } // 输出Sephirex 王思聪 国名老公 for (let key of arr.keys()){ console.log(key); } // 输出0 1 2 // ----------------------- entries( ) :遍历数组 --------------------------------------------- let arr=["Sephirex", "王思聪", "国名老公"]; let list=arr.entries(); console.log(list.next().value); console.log(list.next().value); console.log(list.next().value); // entries()实例方式生成的是Iterator形式的数组,在需要时可以用next()手动跳转到下一个值 // ----------------------- 数组的函数解构 --------------------------------------------- let arr=["Sephirex", "王思聪", "国名老公"]; function fun(a, b, c){ console.log(a, b, c); } fun(...arr); // 控制台打印:Sephirex 王思聪 国名老公 ≈ 执行了 func([a, b, c] = [...arg]) // ------------------------ in的用法 ---------------------------------------------- // 对象判断: let obj={ a:'jack', b:'马云' } console.log('a' in obj); // true // 数组判断 let arr=[,,,,,]; console.log(arr.length); // 输出5,但是数组中其实全是空值 // in方法: let arr=[,,,,,]; console.log(0 in arr); // false let arr1=['jack','马云']; console.log(0 in arr1); // true // ------------------------ 数组遍历大法 ---------------------------------------------- // 1.forEach() // 2.filter() // 3.some() // 4.map() // ------------------------ 数组转字符串 ---------------------------------------------- // 1.join() // 2.toString()
-
箭头函数和扩展
=>
不只是关键字function的简写,箭头函数与包围它的代码共享同一个this,
能帮你很好的解决this的指向问题。有经验的JavaScript开发者都熟悉诸如var self = this;
或var that = this
这种引用外围this的模式。但借助=>
,就不需要这种模式了。箭头函数的结构
=>箭头之前:
a. 一个空括号
b. 单个的参数名
c. 括号括起的多个参数名
=>箭头之后:
a. 一个表达式(作为函数的返回值)
b. 用花括号括起的函数体(需要自行通过return来返回值,否则返回的是undefined)。()=>1 v=>v+1 (a, b)=>a+b ()=>{ alert("foo"); } e=>{ if (e == 0){ return 0; } return 1000/e; }
-
对象
对象赋值
let name="Stephen"; let skill= 'web'; var obj= {name, skill}; console.log(obj); //Object {name: "Stephen", skill: "web"}
对象Key值构建let key='skill'; var obj={ [key]:'web' // 采用中括号形式进行对象构建 } console.log(obj.skill); // web
自定义对象方法var obj={ add:function(a,b){ return a+b; } } console.log(obj.add(1,2)); // 3
Object.is() 、 == 和 ===var obj1 = {name:'jack'}; var obj2 = {name:'jack'}; console.log(obj1.name === obj2.name); // true console.log(Object.is(obj1.name, obj2.name)); //true console.log(2 == '2'); // true console.log(2 === '2'); // false console.log(+0 === -0); // true console.log(NaN === NaN ); // false NaN跟自身不等 console.log(Object.is(+0,-0)); // false console.log(Object.is(NaN,NaN)); // true
区别:==两边数据类型不同时自动先做类型转换,再进行比较,===为同值同类型相等,is()为严格相等
Object.assign( )合并对象
var a={a:'Sephirex'}; var b={b:'王思聪'}; var c={c:'国名老公'}; let d=Object.assign(a, b, c) console.log(d); // {a: "Sephirex", b: "王思聪", c: "国名老公"}
-
Symbol
let obj={name:'Stephen',skill:'web'}; let age=Symbol(); obj[age]=18; for (let item in obj){ console.log(obj[item]); // Stephen web } console.log(obj); // {name: "Stephen", skill: "web", Symbol(): 18} 保护元素,隐藏年龄
-
Set和Map
Set声明
let setArr = new Set(['Sephirex','王思聪','热狗','Sephirex']); console.log(setArr); // Set {"Sephirex", "王思聪", "热狗"}
Set和Array区别:Set不允许内部有重复的值
Set的相关操作
let setArr = new Set(['Sephirex','王思聪','热狗','Sephirex']); console.log(setArr); // Set {"Sephirex", "王思聪", "热狗"} // -------------------------------------- add ------------------------------------------------------------------- setArr.add('真香'); console.log(setArr); // Set {"Sephirex", "王思聪", "热狗", "真香"} // -------------------------------------- delete ------------------------------------------------------------------- setArr.delete('真香'); console.log(setArr); // Set {"Sephirex", "王思聪", "热狗"} // -------------------------------------- Retrieve ------------------------------------------------------------------- console.log(setArr.has('Sephirex')); //true // -------------------------------------- clear清空 ------------------------------------------------------------------- setArr.clear(); console.log(setArr) // Set {} // -------------------------------------- Set遍历: for of ------------------------------------------------------------------- for (let item of setArr){ console.log(item); } // -------------------------------------- Set的size属性 ------------------------------------------------------------------- console.log(setArr.size); // 3 // -------------------------------------- Set的forEach循环 ------------------------------------------------------------------- setArr.forEach((value) => console.log(value));
Json和Map:
let json = { name:'Stephen', skill:'web' } console.log(json.name); // Stephen var map=new Map(); map.set(json,'iam'); console.log(map);
// -------------------------------------- 获取json key对应value ------------------------------------------------------------------- console.log(map.get(json)); // iam // -------------------------------------- 删除json key对应键值对 ------------------------------------------------------------------- map.delete(json); console.log(map) // Map {} // -------------------------------------- 获取map size ------------------------------------------------------------------- console.log(map.size) // 1 // -------------------------------------- 查找是否存在has ------------------------------------------------------------------- consolec .log(map.has('Stephen')) // true // -------------------------------------- 清楚所有元素clear ------------------------------------------------------------------- map.clear()
-
Proxy
Proxy就像一个钩子函数,然你在对象与各种操作对象的行为之间收集与请求相作的各种信息,并返回任何你想做的。
// -------------------------------------- ES5定义对象 ------------------------------------------------------------------- var obj={ add:function(val){ return val+10; }, name:'I am Stephen' }; console.log(obj.add(100)); // 110 console.log(obj.name); // I am Stephen // -------------------------------------- 声明Proxy ------------------------------------------------------------------- new Proxy({},{}); // 第一个花括号为方法的主体,第二个花括号为Proxy代理处理区域,相当于写钩子函数的地方。 // -------------------------------------- 改造传统定义对象方式 ------------------------------------------------------------------- var pro = new Proxy({ add: function (val) { return val + 10; }, name: 'I am Stephen' }, { get:function(target, key, property){ console.log('come in Get'); return target[key]; } }); console.log(pro.name); // 先输出 come in Get,这里相当于方法调用前执行的钩子 // 再输出 I am Stephen
get、set、apply用法
get属性
get属性是在你得到某对象属性值时预处理的方法,接收三个参数
target:得到的目标值
key:目标的key值,相当于对象的属性
property:这个不太常用
set属性
set属性是值你要改变Proxy属性值时,进行的预先处理。接收四个参数。
target:目标值。
key:目标的Key值。
value:要改变的值。
receiver:改变前的原始值。
apply
在方法体是一个匿名函数时,调用内部的方法。var target = function () { return 'I am Stephen'; }; var handler = { apply(target, ctx, args) { console.log('do apply'); return Reflect.apply(...arguments); } } var pro = new Proxy(target, handler); console.log(pro()); // 先输出do apply,再输出I am Stephen
-
Promise
Promise是异步编程的一种解决方案,比传统的解决方案callback更加的优雅。
// ----------------------------------- 举例日常海底捞吃饭 ------------------------------------------------------------------ let state=1; function step1(resolve, reject){ console.log('1.开始-点菜'); if(state==1){ resolve('点菜--完成'); }else{ reject('点菜--出错'); } } function step2(resolve, reject){ console.log('2.开始-上菜吃饭'); if(state==1){ resolve('上菜吃饭--完成'); }else{ reject('上菜吃饭--出错'); } } function step3(resolve, reject){ console.log('3.开始-买单'); if(state==1){ resolve('买单--完成'); }else{ reject('买单--出错'); } } new Promise(step1).then((val) => { console.log(val); return new Promise(step2); }).then((val) => { console.log(val); return new Promise(step3); }).then((val) => { console.log(val); return val; }); // 这个过程是有一定的顺序的,你必须保证上一步完成,才能顺利进行下一步
-
类
ES5中经常使用方法或者对象去模拟类的使用,虽然可以实现功能,但是代码并不优雅
// ----------------------------------- 类的声明 ------------------------------------------------------------------ class Coder{ name(val){ console.log(val); } } // ----------------------------------- 类的使用 ------------------------------------------------------------------ let Sephirex = new Coder; Sephirex.name('思聪'); // 思聪 // ----------------------------------- 类的多方法声明 ------------------------------------------------------------------ class Coder{ name(val){ console.log(val); return val; } skill(val){ console.log(this.name('Sephirex')+':'+'Skill:'+val); } } let Sephirex = new Coder; Sephirex.name('思聪'); // 思聪 Sephirex.skill('web'); // this.name('Sephirex')调用内部方法打印并返回Sephirex Sephirex:Skill:web // ----------------------------------- 类的传参 ------------------------------------------------------------------ class Coder{ name(val){ console.log(val); return val; } skill(val){ console.log(this.name('Sephirex')+':'+'Skill:'+val); } constructor(a, b){ this.a=a; this.b=b; } add(){ return this.a+this.b; } } let Sephirex = new Coder(1,2); console.log(Sephirex.add()); // 用constructor()进行传参。传递参数后可以直接使用this.xxx 进行调用,返回结果:3 // ----------------------------------- 类的继承 ------------------------------------------------------------------ class Ceo extends Coder{ } let shuaibi = new Ceo; shuaibi.name('巨超');
-
模块化
ES5不支持原生的模块化,模块的功能主要由 export 和 import 组成。
// ---------- export 把变量、函数、对象进行模块话,提供外部调用接口,让外部引用 -------------------------------------------------------- // 新建一个文件tmp.js export var a = 'Sephirex'; // 在index.js中引入a变量 import {a} from './tmp.js'; console.log(a); // Sephirex // ---------- 多变量输出 --------------------------------- var a ='Sephirex'; var b ='王思聪'; var c = '热狗'; export {a, b, c} // ---------- 函数模块化输出 ----------------------------- export function add(a, b){ return a+b; } // ---------- as的用法:不暴露源模块中的变量名 ----------------------------- export { x as a, y as b, z as c } import {x, y, z} from './tmp'; console.log(x,y,z) // Sephirex 王思聪 热狗 // ---------- export default一个文件中只能有一个 -----------------------------