面试

ES6常用新特性和语法。

一、变量申明

ES6有var、function、let、const、import、class6种变量申明方式。
    let和const相比于var,主要区别是作用域变为块级(块级内有效),其他有 变量不可提升(获取变量在变量命名之前会报错,var只会得到undefined)和暂时性死区间(变量声明了,在该区域内声明该变量前使用该变量会报错)。
    块级作用域的出现原因:带来很多不合理场景,主要场景有:
1、内部变量因为变量提升而覆盖外部变量。

内部变量tmp变量提升,值为undefined,覆盖了外部变量tmp

2、for循环。若用var,再循环结束后并不会消失而会泄漏为全局变量。若用let,只会在每个循环体内有效,循环结束就会消失。
3、使得立即执行函数(function(){}())不再必要,它的目的是为了创造独立、不被污染的变量空间,会计作用域做到了。

二、模块化

    模块化有ES6规范(export/export.default)、服务端CommonJS规范(exports/module.exports)、浏览器端UMD(AMD/CMD)规范。
    CommonJS 定义了很多普通应用程序(主要指非浏览器的应用)使用的API,填补了JS官方定义的API只能构建基于浏览器的应用程序的空白,Node.js就是它的产物之一。它的模块化规范无法使用在客户端,是因为客户端对模块需要异步加载,加载时间取决于网速。而服务端的模块都在本地磁盘,不用考虑加载时间问题。
    UMD,即AMD(require.js)和CMD(sea.js)。1、两者写法不同,AMD依赖写在最前面;CMD依赖需要用到时再写进来。2、两者依赖加载时机不同,AMD等全部依赖加载好,执行好,再开始执行回调函数;CMD先通过正则把依赖匹配出来先加载好,然后开始执行回调函数,回调函数中遇到依赖再去执行依赖。
    ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 UMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。未来不再需要UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。目前,通过各种工具库,其实已经做到了这一点。

上面代码的实质是整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。上面代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高。当然,这也导致了没法引用 ES6 模块本身,因为它不是对象。

三、解构赋值

最大的作用就是减少了代码量,原来需要进行“xxx=xxx”赋值的方式,按照变量结构模式进行自动匹配赋值,减少"等号"赋值步骤。

用途场景:1、不同变量的值交换变的很方便。比如交换变量的值,不用再把变量对应的值通过“等号”进行交换。2、从一个大变量中分别取到小变量变的很方便。比如直接能从JSON对象中分别取到几个想要的值。

四、异步编程解决方案

回调函数(express),就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。

读取文件进行处理,是这样写的。等到操作系统返回了/etc/passwd这个文件以后,回调函数才会执行

Promise,异步编程的一种解决方案,比传统的解决方案(回调函数)更合理更强大。主要体现在:
1、可以把异步操作对象以同步操作的流程表达出来,避免了层层嵌套的回调函数。缺点是代码冗余,原来的任务被promise包装,不管什么操作都是一堆then,语义不清晰。(可以想象多个异步程序,通过回调函数a调用回调函数b,d调用c...。而promesi直接通过.then(resolve,reject)可以链式调用。)
2、Promise对象提供统一的接口,使得控制异步操作更加容易。

可以看到,Promise 的写法只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。

Generator(koa),函数是ES6提供的一种异步编程解决方案,它会返回一个遍历器对象,可依次遍历G函数内部的每一个状态。我们可以通过next来控制G函数进入下一个状态,通过yeild来控制返回G函数当前状态并暂停执行(我们可以通过next()控制执行权交给谁)。控制流程更加灵活。代码精简。

定义流程
执行流程

async函数(koa2),是Generator函数的语法糖语意更清晰内置执行器,可以直接执行函数a(),不用借助next()一步步执行或co模块自动执行。返回promise对象,可以用then方法指定下一步的操作,比generator返回Iterator更方便。适用性更广,co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
async定义的函数Func返回的值是promise对象(不管其内有没有await),在外部想调用函数直接取到值,要 const data =await Func()。
await相当于promise的then,上一步运算完了才会执行await 这一步。

函数扩展

1、箭头函数,不仅仅让语法变得更精简,解决了匿名函数、setTimeout、setInterval中this指向问题。

2、函数形参可以设置默认值。

3、函数中可以用rest 参数(...变量名),rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。代替arguments(arguments对象不是数组,而是一个类似数组的对象),且比arguments更好用,

数组扩展

1、扩展运算符(...),将一个数组转为用逗号分隔的参数序列。

2、find(function(e,i,arr){..})所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined.
findIndex(function(e,i,arr) {...)返回第一个符合条件的数组成员的位置

字符串扩展

1、字符串具有遍历器接口,能用for..of遍历。

2、模版字符串,反引号 `,其内插入变量,执行函数都非常方便。

你可能感兴趣的:(面试)