ES6 面试题精选4

25 谈一谈你了解 ECMAScript6 的新特性?


  • 块级作用区域 let a = 1;
  • 可定义常量 const PI = 3.141592654;
  • 变量解构赋值 var [a, b, c] = [1, 2, 3];
  • 字符串的扩展(模板字符串) var sum =${a + b};
  • 数组的扩展(转换数组类型) Array.from($('li'));
  • 函数的扩展(扩展运算符) [1, 2].push(...[3, 4, 5]);
  • 对象的扩展(同值相等算法) Object.is(NaN, NaN);
  • 新增数据类型(Symbol) let uid = Symbol('uid');
  • 新增数据结构(Map) let set = new Set([1, 2, 2, 3]);
  • for…of 循环 for(let val of arr){};
  • Promise 对象 var promise = new Promise(func);
  • Generator 函数 function* foo(x){yield x; return x*x;}
  • 引入 Class(类) class Foo {}
  • 引入模块体系 export default func;
  • 引入 async 函数[ES7]
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value)
}

与原来的比较操作符 ===、== 的区别?


  • == 相等运算符,比较时会自动进行数据类型转换
  • === 严格相等运算符,比较时不进行隐式类型转换
  • Object.is 同值相等算法,在 === 基础上对 0NaN 特别处理
+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

27 什么是 Babel


  • Babel 是一个 JS 编译器,自带一组 ES6 语法转化器,用于转化 JS 代码。 这些转化器让开发者提前使用最新的 JS 语法(ES6/ES7),而不用等浏览器全部兼容。
  • Babel 默认只转换新的 JS 句法(syntax),而不转换新的 API。

28 symbol 有什么用处


可以用来表示一个独一无二的变量防止命名冲突。但是面试官问还有吗?我没想出其他的用处就直接答我不知道了,还可以利用  symbol 不会被常规的方法(除了  Object.getOwnPropertySymbols 外)遍历到,所以可以用来模拟私有变量。

主要用来提供遍历接口,布置了  symbol.iterator 的对象才可以使用  for···of 循环,可以统一处理数据结构。调用之后回返回一个遍历器对象,包含有一个 next 方法,使用 next 方法后有两个返回值 value 和 done 分别表示函数当前执行位置的值和是否遍历完毕。

Symbol.for()` 可以在全局访问 `symbol

29 模块化


在有 Babel 的情况下,我们可以直接使用 ES6的模块化

// file a.js
export function a() {}
export function b() {}
// file b.js
export default function() {}

import {a, b} from './a.js'
import XXX from './b.js'

CommonJS

CommonJsNode 独有的规范,浏览器中使用就需要用到 Browserify解析了。

// a.js
module.exports = {
a: 1
}
// or
exports.a = 1

// b.js
var module = require('./a.js')
module.a // -> log 1

在上述代码中,module.exportsexports 很容易混淆,让我们来看看大致内部实现

var module = require('./a.js')
module.a
// 这里其实就是包装了一层立即执行函数,这样就不会污染全局变量了,
// 重要的是 module 这里,module 是 Node 独有的一个变量
module.exports = {
a: 1
}
// 基本实现
var module = {
exports: {} // exports 就是个空对象
}
// 这个是为什么 exports 和 module.exports 用法相似的原因
var exports = module.exports
var load = function (module) {
// 导出的东西
var a = 1
module.exports = a
return module.exports
};

再来说说 module.exportsexports,用法其实是相似的,但是不能对 exports 直接赋值,不会有任何效果。

对于 CommonJSES6 中的模块化的两者区别是:

  • 前者支持动态导入,也就是 require(${path}/xx.js),后者目前不支持,但是已有提案,前者是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线程影响也不大。
  • 而后者是异步导入,因为用于浏览器,需要下载文件,如果也采用同步导入会对渲染有很大影响
  • 前者在导出时都是值拷贝,就算导出的值变了,导入的值也不会改变,所以如果想更新值,必须重新导入一次。
  • 但是后者采用实时绑定的方式,导入导出的值都指向同一个内存地址,所以导入值会跟随导出值变化
  • 后者会编译成 require/exports 来执行的

AMD

AMD 是由 RequireJS 提出的

// AMD
define(['./a', './b'], function(a, b) {
a.do()
b.do()
})
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
var b = require('./b')
b.doSomething()
})

30 箭头函数的特点


function a() {
return () => {
return () => {
console.log(this)
}
}
}
console.log(a()()())

箭头函数其实是没有 this 的,这个函数中的 this 只取决于他外面的第一个不是箭头函数的函数的 this。在这个例子中,因为调用 a 符合前面代码中的第一个情况,所以 thiswindow。并且 this一旦绑定了上下文,就不会被任何代码改变

31 ES5 / ES6 的继承除了写法以外还有什么区别


  • ES5 的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到 this 上(Parent.apply(this))
  • ES6 的继承机制完全不同,实质上是先创建父类的实例对象 this(所以必须先调用父类的 super()方法),然后再用子类的构造函数修改 this。
  • ES5 的继承时通过原型或构造函数机制来实现。
  • ES6 通过 class 关键字定义类,里面有构造方法,类之间通过 extends 关键字实现继承。
  • 子类必须在 constructor 方法中调用 super 方法,否则新建实例报错。因为子类没有自己的 this 对象,而是继承了父类的 this 对象,然后对其进行加工。如果不调用 super 方法,子类得不到 this 对象。
  • 注意 super 关键字指代父类的实例,即父类的 this 对象。
  • 注意:在子类构造函数中,调用 super 后,才可使用 this 关键字,否则报错。function 声明会提升,但不会初始化赋值。Foo 进入暂时性死区,类似于 let、const 声明变量

32 全局作用域中,用 const 和 let 声明的变量不在 window 上,那到底在哪里?如何去获取?


// 在 ES5 中,顶层对象的属性和全局变量是等价的,var 命令和 function 命令声明的全局变量,自然也是顶层对象。
var a = 12;
function f(){};
console.log(window.a);
// 12console.log(window.f);
// f(){}

// 但 ES6 规定,var 命令和 function 命令声明的全局变量,依旧是顶层对象的属性,但 let 命令、const 命令、class 命令声明的全局变量,不属于顶层对象的属性。
let aa = 1;
const bb = 2;
console.log(window.aa);
// undefinedconsole.log(window.bb);
// undefined

// 在哪里?怎么获取?通过在设置断点,看看浏览器是怎么处理的:
//通过上图也可以看到,在全局作用域中,用 let 和 const 声明的全局变量并没
//有在全局对象中,只是一个块级作用域(Script)中怎么获取?在定义变量的块级作用域中就能获取啊,既然不属于顶层对象,那就不加 window(global)呗。
let aa = 1;
const bb = 2;
console.log(aa);
// 1console.log(bb);
// 2

33 介绍下 Set、Map、WeakSet 和 WeakMap 的区别


Set

  • 成员不能重复
  • 只有健值,没有健名,有点类似数组
  • 可以遍历,方法有add, delete,has

weakSet

  • 成员都是对象
  • 成员都是弱引用,随时可以消失。 可以用来保存 DOM 节点,不容易造成内存泄漏
  • 不能遍历,方法有add, delete,has

Map

  • 本质上是健值对的集合,类似集合
  • 可以遍历,方法很多,可以干跟各种数据格式转换

weakMap

  • 直接受对象作为健名(null除外),不接受其他类型的值作为健名
  • 健名所指向的对象,不计入垃圾回收机制
  • 不能遍历,方法同get,set,has,delete

原文始发于微信公众号(消失的程序员):ES6 面试题精选4

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/250716.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!