2020前端面试真题( ES6 )_江理彭于晏的博客-程序员宅基地

技术标签: 前端面试要点  ES6面试题  

JS部分
HTML + CSS
React
Vue
ES6
webpack,node.js,Git等

ES6 阮一峰ES6入门教程

1.使用箭头函数应注意什么?

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
(2)不能够使用arguments对象
(3)不能用作构造函数,所以不能使用new命令,否则会报错
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数
(5)没有原型和super
(6)call/apply/bind方法无法改变箭头函数中this的指向

2.简述es6的新特性

  1. 增加块作用域
  2. 增加let const
  3. 解构赋值
  4. 函数参数扩展 (函数参数可以使用默认值、不定参数以及拓展参数)
  5. 增加class类的支持
  6. 增加箭头函数
  7. 增加模块和模块加载
  8. 增加新的API math, number, string, array, object

3.ES6 module和commonjs的区别

JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,在 ES6 之前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。ES6 可以在编译时就完成模块加载,效率要比 CommonJS 模块的加载方式高
ES6module的语法

4.ES6中的Generator

Generator函数是ES6提供的一种异步编程解决方案。语法上,Generator可以理解为是一个状态机,封装了多个内部状态。执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

  • Generator写法
    下面四种写法均可
function * foo(x, y) {
     ··· }
function *foo(x, y) {
     ··· }
function* foo(x, y) {
     ··· }  // 推荐写法
function*foo(x, y) {
     ··· }
  • 执行机制
    每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。
function* helloWorldGenerator() {
    
  yield 'hello';
  yield 'world';
  return 'ending';
}
var hw = helloWorldGenerator();

hw.next()  // { value: 'hello', done: false }
hw.next()  // { value: 'world', done: false }
hw.next()  // { value: 'ending', done: true }
hw.next()  // { value: undefined, done: true }

调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

  • 与 Iterator 接口的关系
    由于 Generator 函数就是遍历器生成函数,因此可以把 Generator 赋值给对象的Symbol.iterator属性,从而使得该对象具有 Iterator 接口。
var myIterable = {
    };
myIterable[Symbol.iterator] = function* () {
    
  yield 1;
  yield 2;
  yield 3;
};

[...myIterable] // [1, 2, 3]
  • next()的参数
    yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
function* foo(x) {
    
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}

var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}

var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }

上面代码中,第二次运行next方法的时候不带参数,导致 y 的值等于2 * undefined(即NaN),除以 3 以后还是NaN,因此返回对象的value属性也等于NaN。第三次运行Next方法的时候不带参数,所以z等于undefined,返回对象的value属性等于5 + NaN + undefined,即NaN。

如果向next方法提供参数,返回结果就完全不一样了。上面代码第一次调用b的next方法时,返回x+1的值6;第二次调用next方法,将上一次yield表达式的值设为12,因此y等于24,返回y / 3的值8;第三次调用next方法,将上一次yield表达式的值设为13,因此z等于13,这时x等于5,y等于24,所以return语句的值等于42。

注意,由于next方法的参数表示上一个yield表达式的返回值,所以在第一次使用next方法时,传递参数是无效的。V8 引擎直接忽略第一次使用next方法时的参数,只有从第二次使用next方法开始,参数才是有效的。从语义上讲,第一个next方法用来启动遍历器对象,所以不用带有参数。

Genterator应用

  1. 异步操作的同步化表达
    Generator 函数的暂停执行的效果,意味着可以把异步操作写在yield表达式里面,等到调用next方法时再往后执行
//Genterator实现异步请求数据
function* main() {
    
  var result = yield request("http://some.url");
  var resp = JSON.parse(result);
    console.log(resp.value);
}

function request(url) {
    
  makeAjaxCall(url, function(response){
    
    it.next(response);
  });
}

var it = main();
it.next();
  1. 控制流管理
    如果有一个多步操作非常耗时,采用回调函数,可能会写成下面这样。
Promise.resolve(step1)
  .then(step2)
  .then(step3)
  .then(step4)
  .then(function (value4) {
    
    // Do something with value4
  }, function (error) {
    
    // Handle any error from step1 through step4
  })
  .done();

//Generator改造后
function* longRunningTask(value1) {
    
  try {
    
    var value2 = yield step1(value1);
    var value3 = yield step2(value2);
    var value4 = yield step3(value3);
    var value5 = yield step4(value4);
    // Do something with value4
  } catch (e) {
    
    // Handle any error from step1 through step4
  }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/good_father/article/details/112198265

智能推荐

随便推点