前端最新面试题(ES6模块篇)

目录

1 ES5、ES6和ES2015有什么区别?

2 babel是什么,有什么作用?

3 let有什么用,有了var为什么还要用let?

4 举一些ES6对String字符串类型做的常用升级优化?

5 举一些ES6对Array数组类型做的常用升级优化

6 举一些ES6对Number数字类型做的常用升级优化

7 举一些ES6对Object类型做的常用升级优化

8 举一些ES6对Function函数类型做的常用升级优化?

9 Symbol是什么,有什么作用?

10 Set是什么,有什么作用?

11 Map是什么,有什么作用?

12 Proxy是什么,有什么作用?

13 Reflect是什么,有什么作用?

14 Promise是什么,有什么作用?

15 Iterator是什么,有什么作用?

16 for...in 和for...of有什么区别?

17 Generator函数是什么,有什么作用?

generator 原理

Generator 实现

18 async函数是什么,有什么作用?

19 Class、extends是什么,有什么作用?

20 module、export、import是什么,有什么作用?

21 日常前端代码开发中,有哪些值得用ES6去改进的编程优化或者规范?

22 ES6的了解

23 说说你对Promise的理解

24 Promise 的构造函数

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

26 Object.is() 与原来的比较操作符 ===、== 的区别?

27 什么是 Babel

28 symbol 有什么用处

29 模块化

30 箭头函数的特点

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

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

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

34 Promise.all() 和 Promise.allSettled()的比较

Promise.allSettled()

Promise.all()


ES2015 特指在2015 年发布的新一代JS 语言标准,ES6 泛指下一代JS 语言标准,包含ES2015 、ES2016 、ES2017 、ES2018 等。现阶段在绝大部分场景下,ES2015 默认等同ES6 。ES5 泛指上一代语言标准。ES2015 可以理解为ES5 和ES6 的时间分界线

babel 是一个 ES6 转码器,可以将 ES6 代码转为 ES5 代码,以便兼容那些还没支持ES6 的平台

ES6 之前,声明变量只能用var ,var 方式声明变量其实是很不合理的,准确的说,是因为ES5 里面没有块级作用域是很不合理的。没有块级作用域回来带很多难以理解的问题,比如for 循环var 变量泄露,变量覆盖等问题。let 声明的变量拥有自己的块级作用域,且修复了var 声明变量带来的变量提升问题。

优化部分

ES6 新增了字符串模板,在拼接大段字符串时,用反斜杠( )`取代以往的字符串相加的形式,能保留所有空格和换行,使得字符串拼接看起来更加直观,更加优雅

升级部分

ES6 在String 原型上新增了includes() 方法,用于取代传统的只能用indexOf 查找包含字符的方法(indexOf 返回-1 表示没查到不如includes 方法返回false 更明确,语义更清晰), 此外还新增了startsWith() , endsWith(), padStart() ,padEnd() ,repeat() 等方法,可方便的用于查找,补全字符串

优化部分

  • 数组解构赋值。ES6 可以直接以let [a,b,c] = [1,2,3] 形式进行变量赋值,在声明较多变量时,不用再写很多let(var), 且映射关系清晰,且支持赋默认值
  • 扩展运算符。ES6 新增的扩展运算符(... )(重要),可以轻松的实现数组和松散序列的相互转化,可以取代arguments 对象和apply 方法,轻松获取未知参数个数情况下的参数集合。(尤其是在ES5 中,arguments 并不是一个真正的数组,而是一个类数组的对象,但是扩展运算符的逆运算却可以返回一个真正的数组)。扩展运算符还可以轻松方便的实现数组的复制和解构赋值(let a = [2,3,4] ; let b = [...a] )

升级部分

ES6 在Array 原型上新增了find() 方法,用于取代传统的只能用indexOf 查找包含数组项目的方法,且修复了indexOf 查找不到NaN的bug([NaN].indexOf(NaN) === -1) .此外还新增了copyWithin() ,includes() , fill() ,flat() 等方法,可方便的用于字符串的查找,补全,转换等

优化部分

ES6在Number 原型上新增了isFinite() , isInteger(),isNaN() 方法,用来取代传统的全局isFinite(), isNaN() 方法检测数值是否有限、是否是NaN 。ES5 的isFinite() , isNaN() 方法都会先将非数值类型的参数转化为Number 类型再做判断,这其实是不合理的,最造成isNaN('NaN') === true 的奇怪行为--'NaN' 是一个字符串,但是isNaN 却说这就是NaN 。而Number.isFinite() 和Number.isNaN() 则不会有此类问题(Number.isNaN('NaN') === false )。(isFinite() 同上)

升级部分

ES6 在Math 对象上新增了Math.cbrt() ,trunc() ,hypot() 等等较多的科学计数法运算方法,可以更加全面的进行立方根、求和立方根等等科学计算

let a = 5;
 //isFinite 判断是不是数字,如果是数字,就返回true,不是就返回false。
 console.log(Number.isFinite(a))    // 结果 true

let bb = 452;
// isInteger 判断是不是整数,如果是整数就返回true,不是就false。
console.log(Number.isInteger(bb));

console.log(Number.isNaN('number'))
     //主要用于检测是不是NaN,如果是NaN就返回true,不是就返回false。
     //如果 x 是特殊的非数字值 NaN(或者能被转换为这样的值),返回的值就是 true。如果 x 是其他值,则返回 false。
    // isNaN() 函数可用于判断其参数是否是 NaN,该值表示一个非法的数字(比如被 0 除后得到的结果)。
    // 如果把 NaN 与任何值(包括其自身)相比得到的结果均是 false,所以要判断某个值是否是 NaN,不能使用 == 或 === 运算符。正因为如此,isNaN() 函数是必需的。
   


优化部分

对象属性变量式声明。ES6 可以直接以变量形式声明对象属性或者方法,。比传统的键值对形式声明更加简洁,更加方便,语义更加清晰

let [apple, orange] = ['red appe', 'yellow orange']
let myFruits = {
  apple,
  orange,
}
// let myFruits = {apple: 'red appe', orange: 'yellow orange'};

尤其在对象解构赋值(见优化部分b.)或者模块输出变量时,这种写法的好处体现的最为明显 

let { keys, values, entries } = Object
let MyOwnMethods = {
  keys,
  values,
  entries,
}
// let MyOwnMethods = {keys: keys, values: values, entries: entries}

可以看到属性变量式声明属性看起来更加简洁明了。方法也可以采用简洁写法

let es5Fun = {
  method: function () {},
}
let es6Fun = {
  method() {},
}

 对象的解构赋值。 ES6 对象也可以像数组解构赋值那样,进行变量的解构赋值

let { apple, orange } = {
  apple: 'red appe',
  orange: 'yellow orange',
}

 对象的扩展运算符(... )。 ES6对象的扩展运算符和数组扩展运算符用法本质上差别不大,毕竟数组也就是特殊的对象。对象的扩展运算符一个最常用也最好用的用处就在于可以轻松的取出一个目标对象内部全部或者部分的可遍历属性,从而进行对象的合并和分解

let { apple, orange, ...otherFruits } = {
  apple: 'red apple',
  orange: 'yellow orange',
  grape: 'purple grape',
  peach: 'sweet peach',
}
// otherFruits  {grape: 'purple grape', peach: 'sweet peach'}
// 注意: 对象的扩展运算符用在解构赋值时,扩展运算符只能用在最有一个参数(otherFruits后面不能再跟其他参数)
let moreFruits = {
  watermelon: 'nice watermelon',
}
let allFruits = {
  apple,
  orange,
  ...otherFruits,
  ...moreFruits,
}

 super 关键字。ES6 在Class 类里新增了类似this 的关键字super 。同this 总是指向当前函数所在的对象不同,super 关键字总是指向当前函数所在对象的原型对象

升级部分

ES6 在Object 原型上新增了is() 方法,做两个目标对象的相等比较,用来完善'===' 方法。'===' 方法中NaN === NaN //false 其实是不合理的,Object.is 修复了这个小bug 。(Object.is(NaN, NaN) // true)

ES6 在Object 原型上新增了assign() 方法,用于对象新增属性或者多个对象合并

const target = {
  a: 1,
}
const source1 = {
  b: 2,
}
const source2 = {
  c: 3,
}
Object.assign(target, source1, source2)
target // {a:1, b:2, c:3}

注意 : assign 合并的对象target 只能合并source1 、source2 中的自身属性,并不会合并source1 、source2 中的继承属性,也不会合并不可枚举的属性,且无法正确复制get和set属性(会直接执行get/set 函数,取return 的值)

  • ES6 在Object 原型上新增了getOwnPropertyDescriptors() 方法,此方法增强了ES5 中getOwnPropertyDescriptor() 方法,可以获取指定对象所有自身属性的描述对象。结合defineProperties() 方法,可以完美复制对象,包括复制get 和set 属性
  • ES6 在Object 原型上新增了getPrototypeOf() 和setPrototypeOf() 方法,用来获取或设置当前对象的prototype 对象。这个方法存在的意义在于,ES5 中获取设置prototype 对像是通过__proto__ 属性来实现的,然而__proto__ 属性并不是ES规范中的明文规定的属性,只是浏览器各大产商“私自”加上去的属性,只不过因为适用范围广而被默认使用了,再非浏览器环境中并不一定就可以使用,所以为了稳妥起见,获取或设置当前对象的prototype 对象时,都应该采用ES6新增的标准用法
  • ES6 在Object 原型上还新增了Object.keys() ,Object.values() ,Object.entries() 方法,用来获取对象的所有键、所有值和所有键值对数组

// Object.keys


// 处理对象,返回可枚举的属性数组
let person={
    name:'一只流浪的kk',
    age:20,
    eat:function(){}
}
    console.log(Object.keys(person));//    ['name','age','eat']

// 处理数组,返回索引值数组
 let arr=[1,2,3,4,5];
 console.log(Object.keys(arr));//['0','1','2','3','4','5']

// 处理字符串,返回索引值数组
let str='hello';
console.log(Object.keys(str));//['0','1','2','3','4']
// Object.values()

//返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历属性的键值
let obj = {
    foo : "bar",
    baz : 20
};
console.log(Object.values(obj));  // ["bar", 20]

// 返回数组的成员顺序,与属性的遍历部分介绍的排列规则一致

const obj = {100 : "a", 2 : "b", 7 : "c"};
console.log(Object.values(obj));   //["b", "c", "a"]


// Object.values()只会遍历对象自身的可遍历属性
const obj = Object.create({},{p : {value : 10}});
console.log(Object.values(obj));    
console.log(Object.getOwnPropertyDescriptors(obj)); // []

 Object.create方法的第二个参数添加的对象属性(属性p),如果不显式声明,默认是不可遍历的,因为p的属性描述对象的enumerable默认是false,Object.values不会返回这个属性。
因此只要把enumerable改成true,Object.values就会返回属性p的值。

const obj = Object.create({},{p:{
     value : 10,
     enumerable : true,
     configurable : true,
     writable : true,
}})
console.log(Object.values(obj));    //[10]


//Object.values会过滤属性名为 Symbol 值的属性
//如果Object.values方法的参数是一个字符串,会返回各个字符组成的一个数组。
Object.values({ [Symbol()]: 123, foo: 'abc' });
console.log(Object.values('foo'));  //["f", "o", "o"]
// 如果参数不是对象,Object.values会先将其转为对象
console.log(Object.values(42));  // []
console.log(Object.values(true));  // []
console.log(Object.values(undefined));   //error
console.log(Object.values(null));   //error

Object.entries() 

var obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj));

//如果原对象的属性名是一个 Symbol 值,该属性会被省略

console.log(Object.entries({ [Symbol()]: 123, foo: 'abc' }));  // [ [ 'foo', 'abc' ] ]
// 遍历对象的属性

let obj = {
    one : 1,
    two : 2,
}
for(let [k , v] of Object.entries(obj)){
     console.log(`${JSON.stringify(k)} : ${JSON.stringify(v)}`);
}

// 将对象转为真正的Map结构
const obj = {foo : "bar", baz : 10};
const map = new Map(Object.entries(obj));
console.log(map);
// 实现Object.entries方法
const entries = (obj) => {
     let result = [];
     const objType = typeof(obj);
     if(obj === undefined || obj === null){
          throw new TypeError();
     }
     if(objType === "number" || objType === "boolean"){
         return [];
     }
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值