前端培训-中级阶段(29)- ES6语法(2019-12-12期)

简介: 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。

前言BB



那么我为什么头秃呢?

  1. ECMAScript 6(ES2015) 做了大量的更新。
    那么多的更新我那说的完ECMAScript 6 入门 - 阮一峰,这里发一下学习链接,只能说大佬牛逼。


  1. 2015 年 6 月正式发布。
    现在来说都四年过去了。其实大多数人都掌握了。


  1. 其实还有一个误区不是ES5的都归ES6。其实想想挺逗的。为什么会有这样一个误区?ES2015出来的时候浏览器厂商支持就不一样,ES2016出来之后支持还是不一样,ES2017、ES2018、ES2019 都是这样。这就出现了一个问题,发布是发布了,但是啥时候支持就不一定了。这里放出来我前两天才看的文章,他们的更新速度是真的恐怖。


  1. 从 JavaScript、ES6、ES7 到 ES10,你学到哪儿了? - 疯狂的技术宅
  2. 盘点ES7、ES8、ES9、ES10新特性 - 浪里行舟


提案流程



从提案到正式标准,需要经历五个阶段。每个阶段的变动都需要由 TC39 委员会批准。

  1. Stage 0 - Strawman(展示阶段)
    有人提出的想法(任何人都可以向 TC39 委员会提案,要求修改语言标准)


  1. Stage 1 - Proposal(征求意见阶段)
    想法公布,进行审查与讨论


  1. Stage 2 - Draft(草案阶段)
    想法完善,初始规范


  1. Stage 3 - Candidate(候选人阶段)
    确定要做,完成规范并在浏览器上初步实现。


  1. Stage 4 - Finished(定案阶段)
    到达这里基本就可以在浏览器用了。将添加到下一个年度版本发布中。IE什么的你就不要和我提了


当前的所有提案,可以在 TC39 的官方网站查看


Babel 是什么?



Babel 是一个 JavaScript 编译器。将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。下面列出的是 Babel 能做的事情:


  • 语法转换
  • 通过 Polyfill 方式在目标环境中添加缺失的特性 (通过@babel/polyfill模块)
  • 源码转换 (codemods)


配置文件 .babelrc


{
  // presets字段设定转码规则
  "presets": ["es2015", "react", "stage-2"],
  // 插件
  "plugins": ["transform-decorators-legacy", "transform-class-properties"]
}


执行顺序


  • plugins 在 Presets 前运行。


  • plugins 顺序是从前往后(transform-decorators-legacy、ransform-class-properties)。


  • Preset 顺序是从后往前(stage-2、react、es2015)。


官方预设


官方已经针对常用环境编写了一些 preset:


polyfill


Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,比如 IteratorGeneratorSetMapProxyReflectSymbolPromise 等全局对象,以及一些定义在全局对象上的方法(比如Object.assignArray.includes)都不会转码。


所以我们还需要使用 babel-polyfill


ES6



后面的东西其实看不看无所谓,想要学习呢,还是看阮一峰大佬的好了。

我这里说一下我认为ES6更新了一些什么东西。

  1. 标准化(国际化、unicode、规范化、健壮性、跨平台)


  1. 功能方法(之前用奇奇怪怪的方法实现的功能,这次官方给你了)


  1. 便捷(脚本语言玩的就是骚气)


let、const、块级作用域、暂时性死区


在之前没有块级作用域的概念(try{}catch(e){} 可以模拟,性能呵呵呵呵)。这次加入了块级作用域的概念,let 变量,const 常量。


// 输出什么?
for(var i = 0; i<4;i++){};
i // 4
// 输出什么?
for(let i1 = 0; i1<4;i1++){};
i1 //Uncaught ReferenceError: i1 is not defined


变量提升与暂时性死区


大家都知道面试的时候,喜欢搞一些花里胡哨的鬼东西。

提升是说,var 会被提升到最前面执行,所以不会出现i is not defined

死区是说,let 定义的变量,不能在声明前使用。


(function(){
    console.log(1, i) //1 4 
    //4来源于上面的测试例子,不然会是下面这个鬼样子
    //Uncaught ReferenceError: i is not defined
})();
(function(){
    console.log(2, i)
    var i  = 'lilnong.top' //2 undefined
})();
(function(){
    console.log(3, i)
    let i = 'lilnong.top' // Uncaught ReferenceError: Cannot access 'i' before initialization
})();


globalThis


  • 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window


  • 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self


  • Node 里面,顶层对象是global,但其他环境都不支持。


所以提供了一个访问顶层对象的属性。


解构、默认值


  1. 数组解构赋值 let [a, b, c] = [1, 2, 3];
  2. 对象解构赋值 let { foo, bar } = { foo: 'aaa', bar: 'bbb' }
  3. 字符串解构赋值 const [a, b, c, d, e] = 'hello'
  4. 函数参数的解构赋值(这个比较常用)


axios('https://www.lilnong.top/cors/axios-destructuring')
.then(({data})=>console.log(data))
// y取默认值,然后入参第一个的默认值是{}
function move({x = 0, y = 0} = {}) {
  return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
// y没有默认值,第一个入参的默认值是{ x: 0, y: 0 }
function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]


字符串的扩展、模板字符串、unicode


字符串扩展


只能说写起来更爽了。然后就是之前的写法其实不是很好。会浪费空间,效率不高。

${Math.random()}-${Date.now()}-lilnong.top


unicode 更好的支持、codePointAt、fromCodePoint、normalize


面向国际化,以及 emoji。JavaScript 内部,字符以 UTF-16 的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符(Unicode 码点大于0xFFFF的字符),JavaScript 会认为它们是两个字符。


这里有个小插曲,weex 中 Text 组件无法包含 Image 组件,实现流式排列。(富文本组件好像是可以解决)


在实现这个功能的时候,我想到可以把字变成块,然后flex 允许换行。

测试地址,里面用了两种方案来获取大于Oxffff的字符。


  1. for of
  2. codePointAt 判断大于0xFFFF,需要跳字节。charCodeAt是ES5就支持的,只能拿到小于OxFFFF


更多的API


includes、startsWith、endsWith、repeat、padStart、padEnd、trimStart、trimEnd、matchAll


随着原生提供的 API 越来越多,我们慢慢的不需要使用 Loadsh 等工具库。


正则表达式的扩展、断言、unicode


后行断言


JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。

ES2018 引入 后行断言 ,V8 引擎 4.9 版(Chrome 62)已经支持。“先行断言”指的是, x 只有在 y 前面才匹配,必须写成 /x(?=y)/ 。比如,只匹配百分号之前的数字,要写成 /\d+(?=%)/ 。“先行否定断言”指的是, x 只有不在 y 前面才匹配,必须写成 /x(?!y)/ 。比如,只匹配不在百分号之前的数字,要写成 /\d+(?!%)/ ECMAScript 6 入门 - 后行断言 - 阮一峰

数值的扩展、API、指数运算符


更多的API Number.isFinite()、Number.isNaN()、Number.parseInt()、Number.parseFloat()、Number.isInteger()、Number.isSafeInteger()、Number.EPSILON、Number.isSafeInteger()


函数的扩展、默认值、rest参数、箭头函数、尾调用优化


尾调用优化


我们知道,函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。如果在函数 A 的内部调用函数 B ,那么在 A 的调用帧上方,还会形成一个 B 的调用帧。等到 B 运行结束,将结果返回到 A B 的调用帧才会消失。

如果函数 B 内部还调用函数 C ,那就还有一个 C 的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。

rest参数


(()=>arguments)(1,2,3) // 输出什么?Uncaught ReferenceError: arguments is not defined


在兼容函数中arguments无法使用


((...args)=>args)(1,2,3) //有输出什么?[1, 2, 3]


我们可以使用...来把入参收集起来


((a,...args)=>args)(1,2,3) //[2, 3]


甚至我们前面用变量接收,后面整体用...接收


箭头函数


  1. this 指向定义时所在的对象
  2. 不可以使用 arguments 对象


数组的扩展、展开运算符、API、空位的处理


展开


举一个例子你就知道了。去重,虽然这个方法有局限性吧。

[...new Set([12, 2, 3, 12, 31, 2, 11, 2, 1, 2, 1, 21, 1, 2, 3, 1, 23, 12, 3, 12, 31, 11, 1, 2, 2, 31, 2, 3])]


数组的API


Array.from()、Array.of()、Array.prototype.copyWithin()、Array.prototype.find()、Array.prototype.findIndex()、Array.prototype.fill()、Array.prototype.entries()、Array.prototype.keys()、Array.prototype.values()、Array.prototype.includes()、Array.prototype.flat()、Array.prototype.flatMap()、


nodeList = document.querySelectorAll('div');
// ES5的写法
[].slice.call(nodeList);
// ES6的写法
Array.from(nodeList);


对象的扩展、缩写、变量名表达式、展开运算符、API


变量名表达式


当我看到下面的写法的时候,内心是卧槽的。

GET_USER_INFO = 'getBaseUserInfo'
obj = {
    [GET_USER_INFO](){// 第一次看到是vuex里面分开定义获取数据
        console.log(arguments)
    },
    'abc.sdf'(){// vue watch监听改变的时候
        console.log(arguments)
    }
}


bVbByl8.webp.jpg


API


Object.is()、Object.assign()、Object.getOwnPropertyDescriptors()、Object.setPrototypeOf()、Object.getPrototypeOf()、Object.keys()、Object.values()、Object.entries()、Object.fromEntries()


新的类型、新的全局对象


Symbol、Set、Map、Proxy、Reflect、Promise、Iterator、Generator、async、Class、Module

简直了。太多了


相关文章
|
4月前
|
前端开发 JavaScript Java
ES6前端就业课第三课之class
ES6前端就业课第三课之class
42 0
|
1月前
|
XML 前端开发 JavaScript
【前端】深入了解React JSX语法及实例应用
【前端】深入了解React JSX语法及实例应用
16 0
|
1月前
|
前端开发
web前端-HTML-div语法
web前端-HTML-div语法
|
2月前
|
前端开发 JavaScript 小程序
|
2月前
|
前端开发 JavaScript 小程序
【前端】必学知识ES6 1小时学会
【前端】必学知识ES6 1小时学会
29 0
|
3月前
|
移动开发 前端开发 JavaScript
web前端之ES6的实用深度解构赋值方法、复杂的解构赋值
web前端之ES6的实用深度解构赋值方法、复杂的解构赋值
29 1
|
3月前
|
存储 前端开发 JavaScript
前端面试题整理 (ES6篇)
前端面试题整理 (ES6篇)
|
4月前
|
自然语言处理 前端开发 JavaScript
【前端|Javascript第1篇】一文搞懂Javascript的基本语法
【前端|Javascript第1篇】一文搞懂Javascript的基本语法
147 0
|
4月前
|
前端开发 API
[前端学习]ES6进阶学习
[前端学习]ES6进阶学习
28 1
|
4月前
|
JavaScript 前端开发 Java
[前端学习]ES6小史
[前端学习]ES6小史
25 0