精华内容
下载资源
问答
  • ES6面试题

    2020-12-17 21:22:57
    ES6面试题 1.es5和es6的区别,说一下你所知道的es6 ES6新增的一些特性: 1)let声明变量和const声明常量,两个都有块级作用域ES5中是没有块级作用域的,并且var有变量提升,在let中,使用的变量一定要进行声明 2)...

    ES6面试题

    1.es5和es6的区别,说一下你所知道的es6

    ES6新增的一些特性:
    1)let声明变量和const声明常量,两个都有块级作用域ES5中是没有块级作用域的,并且var有变量提升,在let中,使用的变量一定要进行声明
    2)箭头函数ES6中的函数定义不再使用关键字function(),而是利用了()=>来进行定义
    3)模板字符串模板字符串是增强版的字符串,用反引号(`)标识,可以当作普通字符串使用,也可以用来定义多行字符串
    4)解构赋值ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值
    5)for of循环for…of循环可以遍历数组、Set和Map结构、某些类似数组的对象、对象,以及字符串
    6)import、export导入导出ES6标准中,Js原生支持模块(module)。将JS代码分割成不同功能的小块进行模块化,将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用
    7)set数据结构Set数据结构,类似数组。所有的数据都是唯一的,没有重复的值。它本身是一个构造函数
    8)… 展开运算符可以将数组或对象里面的值展开;还可以将多个值收集为一个变量
    9)修饰器 @decorator是一个函数,用来修改类甚至于是方法的行为。修饰器本质就是编译时执行的函数
    10)class 类的继承ES6中不再像ES5一样使用原型链实现继承,而是引入Class这个概念11)async、await使用 async/await, 搭配promise,可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成
    12)promisePromise是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理、强大
    13)SymbolSymbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的
    14)Proxy代理使用代理(Proxy)监听对象的操作,然后可以做一些相应事情

    2.var、let、const之间的区别

    var声明变量可以重复声明,而let不可以重复声明
    var是不受限于块级的,而let是受限于块级
    var会与window相映射(会挂一个属性),而let不与window相映射
    var可以在声明的上面访问变量,而let有暂存死区,在声明的上面访问变量会报错
    const声明之后必须赋值,否则会报错
    const定义不可变的量,改变了就会报错
    const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错

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

    (1)用了箭头函数,this就不是指向window,而是父级(指向是可变的)
    (2)不能够使用arguments对象
    (3)不能用作构造函数,这就是说不能够使用new命令,否则会抛出一个错误
    (4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数

    4.ES6的模板字符串有哪些新特性?并实现一个类模板字符串的功能

    基本的字符串格式化。
    将表达式嵌入字符串中进行拼接。
    ES5()ES6()letname=web;letage=10;letstr={}来界定在ES5时我们通过反斜杠()来做多行字符串或者字符串一行行拼接。 ES6反引号(``)就能解决类模板字符串的功能 let name = 'web'; let age = 10; let str = '你好,{name} 已经 ${age}岁了’
    str = str.replace(/${([^}]*)}/g,function(){
    return eval(arguments[1]);
    })
    console.log(str);//你好,web 已经 10岁了

    5.介绍下 Set、Map的区别?

    应用场景Set用于数据重组,Map用于数据储存Set: 
    (1)成员不能重复
    (2)只有键值没有键名,类似数组
    (3)可以遍历,方法有add, delete,has
    Map:
    (1)本质上是健值对的集合,类似集合
    (2)可以遍历,可以跟各种数据格式转换

    6.Promise构造函数是同步执行还是异步执行,那么 then 方法呢?

    promise构造函数是同步执行的,then方法是异步执行的

    7.setTimeout、Promise、Async/Await 的区别

    事件循环中分为宏任务队列和微任务队列
    其中setTimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行async函数表示函数里面可能会有异步方法,await后面跟一个表达式
    async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行

    8.promise有几种状态,什么时候会进入catch?

    三个状态:
    pending(初始状态)、fulfilled(操作成功)、reject(操作失败)
    两个过程:
    padding -> fulfilled、padding -> rejected当pending为rejectd时,会进入catch

    9.Promise 中reject 和 catch 处理上有什么区别

    reject 是用来抛出异常,catch 是用来处理异常
    reject 是 Promise 的方法,而 catch 是 Promise 实例的方法
    reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch
    网络异常(比如断网),会直接进入catch而不会进入then的第二个回调

    10.如何使用Set去重

    let arr = [12,43,23,43,68,12];
    let item = […new Set(arr)];
    console.log(item);//[12, 43, 23, 68]

    11.forEach、for in、for of三者区别

    forEach更多的用来遍历数组
    for in 一般常用来遍历对象或json
    for of数组对象都可以遍历,遍历对象需要通过和Object.keys()
    for in循环出的是key,for of循环出的是value

    12.深拷贝的原理

    Js的深拷贝发生在对象的赋值上,对象赋值的时候仅仅是一个引用赋值,也就是说两个不同变量名指向的是同一份内存空间;基本数据类型则不存在这样的行为;要完成对象的深拷贝需要使用递归遍历所有对象的属性进行赋值,也可以使用JSON.stringfy和JSON.parse操作。

    13.浅拷贝的原理

    浅拷贝就是创建一个新对象,这个对象对原始对象进行了精确拷贝。若属性是基本类型,拷贝的就是属性的值;若属性是引用类型,拷贝的就是内存地址,若其中一个对象改变了这个地址,就会影响到另一个对象。重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。

    展开全文
  • es6面试题

    2020-07-29 19:53:47
    ES6常见面试题总结 1、es5和es6的区别,说一下你所知道的es6 ECMAScript5,即ES5,是ECMAScript的第五次修订,于2009年完成标准化ECMAScript6,即ES6,是ECMAScript的第六次修订,于2015年完成,也称ES2015ES6是继...

    ES6常见面试题总结

    1、es5和es6的区别,说一下你所知道的es6
    ECMAScript5,即ES5,是ECMAScript的第五次修订,于2009年完成标准化ECMAScript6,即ES6,是ECMAScript的第六次修订,于2015年完成,也称ES2015ES6是继ES5之后的一次改进,相对于ES5更加简洁,提高了开发效率ES6新增的一些特性:
    1)let声明变量和const声明常量,两个都有块级作用域ES5中是没有块级作用域的,并且var有变量提升,在let中,使用的变量一定要进行声明
    2)箭头函数ES6中的函数定义不再使用关键字function(),而是利用了()=>来进行定义
    3)模板字符串模板字符串是增强版的字符串,用反引号(`)标识,可以当作普通字符串使用,也可以用来定义多行字符串
    4)解构赋值ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值
    5)for of循环for…of循环可以遍历数组、Set和Map结构、某些类似数组的对象、对象,以及字符串
    6)import、export导入导出ES6标准中,Js原生支持模块(module)。将JS代码分割成不同功能的小块进行模块化,将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用
    7)set数据结构Set数据结构,类似数组。所有的数据都是唯一的,没有重复的值。它本身是一个构造函数
    8)… 展开运算符可以将数组或对象里面的值展开;还可以将多个值收集为一个变量
    9)修饰器 @decorator是一个函数,用来修改类甚至于是方法的行为。修饰器本质就是编译时执行的函数
    10)class 类的继承ES6中不再像ES5一样使用原型链实现继承,而是引入Class这个概念11)async、await使用 async/await, 搭配promise,可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成
    12)promisePromise是异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理、强大
    13)SymbolSymbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的
    14)Proxy代理使用代理(Proxy)监听对象的操作,然后可以做一些相应事情

    2、var、let、const之间的区别
    var声明变量可以重复声明,而let不可以重复声明
    var是不受限于块级的,而let是受限于块级
    var会与window相映射(会挂一个属性),而let不与window相映射
    var可以在声明的上面访问变量,而let有暂存死区,在声明的上面访问变量会报错
    const声明之后必须赋值,否则会报错
    const定义不可变的量,改变了就会报错
    const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错

    3、使用箭头函数应注意什么?
    (1)用了箭头函数,this就不是指向window,而是父级(指向是可变的)
    (2)不能够使用arguments对象
    (3)不能用作构造函数,这就是说不能够使用new命令,否则会抛出一个错误
    (4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数

    4、ES6的模板字符串有哪些新特性?并实现一个类模板字符串的功能
    基本的字符串格式化。
    将表达式嵌入字符串中进行拼接。
    ES5()ES6()letname=web;letage=10;letstr={}来界定在ES5时我们通过反斜杠()来做多行字符串或者字符串一行行拼接。 ES6反引号(``)就能解决类模板字符串的功能 let name = 'web'; let age = 10; let str = '你好,{name} 已经 ${age}岁了’
    str = str.replace(/${([^}]*)}/g,function(){
    return eval(arguments[1]);
    })
    console.log(str);//你好,web 已经 10岁了

    5、介绍下 Set、Map的区别?
    应用场景Set用于数据重组,Map用于数据储存Set: 
    (1)成员不能重复
    (2)只有键值没有键名,类似数组
    (3)可以遍历,方法有add, delete,has
    Map:
    (1)本质上是健值对的集合,类似集合
    (2)可以遍历,可以跟各种数据格式转换

    6、ECMAScript 6 怎么写 class ,为何会出现 class?
    ES6的class可以看作是一个语法糖,它的绝大部分功能ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法
    //定义类
    class Point {
    constructor(x,y) {
    //构造方法
    this.x = x; //this关键字代表实例对象
    this.y = y;
    } toString() {
    return ‘(’ + this.x + ‘,’ + this.y + ‘)’;
    }
    }

    7、Promise构造函数是同步执行还是异步执行,那么 then 方法呢?
    promise构造函数是同步执行的,then方法是异步执行的

    8、setTimeout、Promise、Async/Await 的区别
    事件循环中分为宏任务队列和微任务队列
    其中setTimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行async函数表示函数里面可能会有异步方法,await后面跟一个表达式
    async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行

    9、promise有几种状态,什么时候会进入catch?
    三个状态:
    pending、fulfilled、reject
    两个过程:
    padding -> fulfilled、padding -> rejected当pending为rejectd时,会进入catch

    10、下面的输出结果是多少
    const promise = new Promise((resolve, reject) => {
    console.log(1);
    resolve();
    console.log(2);
    })

    promise.then(() => {
    console.log(3);
    })

    console.log(4);
    Promise 新建后立即执行,所以会先输出 1,2,而 Promise.then()内部的代码在 当次 事件循环的 结尾 立刻执行 ,所以会继续输出4,最后输出3

    11、使用结构赋值,实现两个变量的值的交换
    let a = 1;let b = 2;
    [a,b] = [b,a];

    12、设计一个对象,键名的类型至少包含一个symbol类型,并且实现遍历所有key
    let name = Symbol(‘name’);
    let product = {
    [name]:“洗衣机”,
    “price”:799
    };
    Reflect.ownKeys(product);

    13、下面Set结构,打印出的size值是多少
    let s = newSet();
    s.add([1]);s.add([1]);
    console.log(s.size);
    答案:2
    两个数组[1]并不是同一个值,它们分别定义的数组,在内存中分别对应着不同的存储地址,因此并不是相同的值都能存储到Set结构中,所以size为2

    14、Promise 中reject 和 catch 处理上有什么区别
    reject 是用来抛出异常,catch 是用来处理异常
    reject 是 Promise 的方法,而 catch 是 Promise 实例的方法
    reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch
    网络异常(比如断网),会直接进入catch而不会进入then的第二个回调

    15、使用class 手写一个promise
    //创建一个Promise的类
    class Promise{
    constructor(executer){//构造函数constructor里面是个执行器
    this.status = ‘pending’;//默认的状态 pending
    this.value = undefined//成功的值默认undefined
    this.reason = undefined//失败的值默认undefined
    //状态只有在pending时候才能改变
    let resolveFn = value =>{
    //判断只有等待时才能resolve成功
    if(this.status == pending){
    this.status = ‘resolve’;
    this.value = value;
    }
    }
    //判断只有等待时才能reject失败
    let rejectFn = reason =>{
    if(this.status == pending){
    this.status = ‘reject’;
    this.reason = reason;
    }
    }
    try{
    //把resolve和reject两个函数传给执行器executer
    executer(resolve,reject);
    }catch(e){
    reject(e);//失败的话进catch
    }
    }
    then(onFufilled,onReject){
    //如果状态成功调用onFufilled
    if(this.status = ‘resolve’){
    onFufilled(this.value);
    }
    //如果状态失败调用onReject
    if(this.status = ‘reject’){
    onReject(this.reason);
    }
    }
    }

    16、如何使用Set去重
    let arr = [12,43,23,43,68,12];
    let item = […new Set(arr)];
    console.log(item);//[12, 43, 23, 68]

    17、将下面for循环改成for of形式
    let arr = [11,22,33,44,55];
    let sum = 0;
    for(let i=0;i<arr.length;i++){
    sum += arr[i];
    }
    答案:
    let arr = [11,22,33,44,55];
    let sum = 0;
    for(value of arr){
    sum += value;
    }

    18、理解 async/await以及对Generator的优势
    async await 是用来解决异步的,async函数是Generator函数的语法糖
    使用关键字async来表示,在函数内部使用 await 来表示异步
    async函数返回一个 Promise 对象,可以使用then方法添加回调函数
    当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
    async较Generator的优势:
    (1)内置执行器。Generator 函数的执行必须依靠执行器,而 Aysnc 函数自带执行器,调用方式跟普通函数的调用一样
    (2)更好的语义。async 和 await 相较于 * 和 yield 更加语义化  
    (3)更广的适用性。yield命令后面只能是 Thunk 函数或 Promise对象,async函数的await后面可以是Promise也可以是原始类型的值
    (4)返回值是 Promise。async 函数返回的是 Promise 对象,比Generator函数返回的Iterator对象方便,可以直接使用 then() 方法进行调用

    19、forEach、for in、for of三者区别
    forEach更多的用来遍历数组
    for in 一般常用来遍历对象或json
    for of数组对象都可以遍历,遍历对象需要通过和Object.keys()
    for in循环出的是key,for of循环出的是value

    20、说一下es6的导入导出模块
    导入通过import关键字
    // 只导入一个
    import {sum} from “./example.js”
    // 导入多个
    import {sum,multiply,time} from “./exportExample.js”
    // 导入一整个模块
    import * as example from “./exportExample.js”
    导出通过export关键字
    //可以将export放在任何变量,函数或类声明的前面
    export var firstName = ‘Michael’;
    export var lastName = ‘Jackson’;
    export var year = 1958;
    //也可以使用大括号指定所要输出的一组变量
    var firstName = ‘Michael’;
    var lastName = ‘Jackson’;
    var year = 1958;
    export {firstName, lastName, year};
    //使用export default时,对应的import语句不需要使用大括号
    let bosh = function crs(){}
    export default bosh;
    import crc from ‘crc’;
    //不使用export default时,对应的import语句需要使用大括号
    let bosh = function crs(){}
    export bosh;
    import {crc} from ‘crc’;

    展开全文
  • 前端ES6面试题

    2020-05-20 14:46:29
    前端ES6面试题 1、ES5、ES6和ES2015有什么区别? ES2015特指在2015年发布的新一代JS语言标准,ES6泛指下一代JS语言标准,包含ES2015、ES2016、ES2017、ES2018等。现阶段在绝大部分场景下,ES2015默认等同ES6。...

    前端ES6面试题

     

     

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

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

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

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

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

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

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

    优化部分

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

    升级部分

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

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

    优化部分

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

    升级部分

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

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

    优化部分

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

    升级部分

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

    7、举一些ES6对Object类型做的常用升级优化?(重要)

    优化部分

    对象属性变量式声明。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 关键字。ES6Class类里新增了类似this的关键字super。同this总是指向当前函数所在的对象不同,super关键字总是指向当前函数所在对象的原型对象

     

    升级部分

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

    ES6Object原型上新增了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中的自身属性,并不会合并source1source2中的继承属性,也不会合并不可枚举的属性,且无法正确复制get和set属性(会直接执行get/set函数,取return的值)

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

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

    优化部分

    箭头函数(核心)。箭头函数是ES6核心的升级项之一,箭头函数里没有自己的this,这改变了以往JS函数中最让人难以理解的this运行机制。主要优化点

    • 箭头函数内的this指向的是函数定义时所在的对象,而不是函数执行时所在的对象。ES5函数里的this总是指向函数执行时所在的对象,这使得在很多情况下this的指向变得很难理解,尤其是非严格模式情况下,this有时候会指向全局对象,这甚至也可以归结为语言层面的bug之一。ES6的箭头函数优化了这一点,它的内部没有自己的this,这也就导致了this总是指向上一层的this,如果上一层还是箭头函数,则继续向上指,直到指向到有自己this的函数为止,并作为自己的this
    • 箭头函数不能用作构造函数,因为它没有自己的this,无法实例化
    • 也是因为箭头函数没有自己的this,所以箭头函数 内也不存在arguments对象。(可以用扩展运算符代替)
    • 函数默认赋值。ES6之前,函数的形参是无法给默认值得,只能在函数内部通过变通方法实现。ES6以更简洁更明确的方式进行函数默认赋值
    function es6Fuc (x, y = 'default') {
        console.log(x, y);
    }
    es6Fuc(4) // 4, default
    

    升级部分

    ES6新增了双冒号运算符,用来取代以往的bindcall,和apply。(浏览器暂不支持,Babel已经支持转码)

    foo::bar;
    // 等同于
    bar.bind(foo);
    
    foo::bar(...arguments);
    // 等同于
    bar.apply(foo, arguments);
    

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

    SymbolES6引入的第七种原始数据类型(说法不准确,应该是第七种数据类型,Object不是原始数据类型之一,已更正),所有Symbol()生成的值都是独一无二的,可以从根本上解决对象属性太多导致属性名冲突覆盖的问题。对象中Symbol()属性不能被for...in遍历,但是也不是私有属性

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

    SetES6引入的一种类似Array的新的数据结构,Set实例的成员类似于数组item成员,区别是Set实例的成员都是唯一,不重复的。这个特性可以轻松地实现数组去重

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

    MapES6引入的一种类似Object的新的数据结构,Map可以理解为是Object的超集,打破了以传统键值对形式定义对象,对象的key不再局限于字符串,也可以是Object。可以更加全面的描述对象的属性

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

    ProxyES6新增的一个构造函数,可以理解为JS语言的一个代理,用来改变JS默认的一些语言行为,包括拦截默认的get/set等底层方法,使得JS的使用自由度更高,可以最大限度的满足开发者的需求。比如通过拦截对象的get/set方法,可以轻松地定制自己想要的key或者value。下面的例子可以看到,随便定义一个myOwnObjkey,都可以变成自己想要的函数`

    function createMyOwnObj() {
    	//想把所有的key都变成函数,或者Promise,或者anything
    	return new Proxy({}, {
    		get(target, propKey, receiver) {
    			return new Promise((resolve, reject) => {
    				setTimeout(() => {
    					let randomBoolean = Math.random() > 0.5;
    					let Message;
    					if (randomBoolean) {
    						Message = `你的${propKey}运气不错,成功了`;
    						resolve(Message);
    					} else {
    						Message = `你的${propKey}运气不行,失败了`;
    						reject(Message);
    					}
    				}, 1000);
    			});
    		}
    	});
    }
    
    let myOwnObj = createMyOwnObj();
    
    myOwnObj.hahaha.then(result => {
    	console.log(result) //你的hahaha运气不错,成功了
    }).catch(error => {
    	console.log(error) //你的hahaha运气不行,失败了
    })
    
    myOwnObj.wuwuwu.then(result => {
    	console.log(result) //你的wuwuwu运气不错,成功了
    }).catch(error => {
    	console.log(error) //你的wuwuwu运气不行,失败了
    })
    
    

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

    ReflectES6引入的一个新的对象,他的主要作用有两点,一是将原生的一些零散分布在ObjectFunction或者全局函数里的方法(如applydeletegetset等等),统一整合到Reflect上,这样可以更加方便更加统一的管理一些原生API。其次就是因为Proxy可以改写默认的原生API,如果一旦原生API别改写可能就找不到了,所以Reflect也可以起到备份原生API的作用,使得即使原生API被改写了之后,也可以在被改写之后的API用上默认的API

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

    PromiseES6引入的一个新的对象,他的主要作用是用来解决JS异步机制里,回调机制产生的“回调地狱”。它并不是什么突破性的API,只是封装了异步回调形式,使得异步回调可以写的更加优雅,可读性更高,而且可以链式调用

    15、Iterator是什么,有什么作用?(重要)

    • IteratorES6中一个很重要概念,它并不是对象,也不是任何一种数据类型。因为ES6新增了SetMap类型,他们和ArrayObject类型很像,ArrayObject都是可以遍历的,但是SetMap都不能用for循环遍历,解决这个问题有两种方案,一种是为SetMap单独新增一个用来遍历的API,另一种是为SetMapArrayObject新增一个统一的遍历API,显然,第二种更好,ES6也就顺其自然的需要一种设计标准,来统一所有可遍历类型的遍历方式。Iterator正是这样一种标准。或者说是一种规范理念
    • 就好像JavaScriptECMAScript标准的一种具体实现一样,Iterator标准的具体实现是Iterator遍历器。Iterator标准规定,所有部署了key值为[Symbol.iterator],且[Symbol.iterator]value是标准的Iterator接口函数(标准的Iterator接口函数: 该函数必须返回一个对象,且对象中包含next方法,且执行next()能返回包含value/done属性的Iterator对象)的对象,都称之为可遍历对象,next()后返回的Iterator对象也就是Iterator遍历器
    //obj就是可遍历的,因为它遵循了Iterator标准,且包含[Symbol.iterator]方法,方法函数也符合标准的Iterator接口规范。
    //obj.[Symbol.iterator]() 就是Iterator遍历器
    let obj = {
      data: [ 'hello', 'world' ],
      [Symbol.iterator]() {
        const self = this;
        let index = 0;
        return {
          next() {
            if (index < self.data.length) {
              return {
                value: self.data[index++],
                done: false
              };
            } else {
              return { value: undefined, done: true };
            }
          }
        };
      }
    };
    
    

    ES6SetMapArrayString都加上了[Symbol.iterator]方法,且[Symbol.iterator]方法函数也符合标准的Iterator接口规范,所以SetMapArrayString默认都是可以遍历的

    //Array
    let array = ['red', 'green', 'blue'];
    array[Symbol.iterator]() //Iterator遍历器
    array[Symbol.iterator]().next() //{value: "red", done: false}
    
    //String
    let string = '1122334455';
    string[Symbol.iterator]() //Iterator遍历器
    string[Symbol.iterator]().next() //{value: "1", done: false}
    
    //set
    let set = new Set(['red', 'green', 'blue']);
    set[Symbol.iterator]() //Iterator遍历器
    set[Symbol.iterator]().next() //{value: "red", done: false}
    
    //Map
    let map = new Map();
    let obj= {map: 'map'};
    map.set(obj, 'mapValue');
    map[Symbol.iterator]().next()  {value: Array(2), done: false}
    
    
    

    16、for…in 和for…of有什么区别?

    如果看到问题十六,那么就很好回答。问题十六提到了ES6统一了遍历标准,制定了可遍历对象,那么用什么方法去遍历呢?答案就是用for...of。ES6规定,有所部署了载了Iterator接口的对象(可遍历对象)都可以通过for...of去遍历,而for..in仅仅可以遍历对象

    这也就意味着,数组也可以用for...of遍历,这极大地方便了数组的取值,且避免了很多程序用for..in去遍历数组的恶习

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

    • 如果说JavaScriptECMAScript标准的一种具体实现、Iterator遍历器是Iterator的具体实现,那么Generator函数可以说是Iterator接口的具体实现方式。
    • 执行Generator函数会返回一个遍历器对象,每一次Generator函数里面的yield都相当一次遍历器对象的next()方法,并且可以通过next(value)方法传入自定义的value,来改变Generator函数的行为。
    • Generator函数可以通过配合Thunk 函数更轻松更优雅的实现异步编程和控制流管理。

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

    async函数可以理解为内置自动执行器的Generator函数语法糖,它配合ES6Promise近乎完美的实现了异步编程解决方案

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

    ES6 的class可以看作只是一个ES5生成实例对象的构造函数的语法糖。它参考了java语言,定义了一个类的概念,让对象原型写法更加清晰,对象实例化更像是一种面向对象编程。Class类可以通过extends实现继承。它和ES5构造函数的不同点

    类的内部定义的所有方法,都是不可枚举的

    ///ES5
    function ES5Fun (x, y) {
    	this.x = x;
    	this.y = y;
    }
    ES5Fun.prototype.toString = function () {
    	 return '(' + this.x + ', ' + this.y + ')';
    }
    var p = new ES5Fun(1, 3);
    p.toString();
    Object.keys(ES5Fun.prototype); //['toString']
    
    //ES6
    class ES6Fun {
    	constructor (x, y) {
    		this.x = x;
    		this.y = y;
    	}
    	toString () {
    		return '(' + this.x + ', ' + this.y + ')';
    	}
    }
    
    Object.keys(ES6Fun.prototype); //[]
    
    
    • ES6class类必须用new命令操作,而ES5的构造函数不用new也可以执行。
    • ES6class类不存在变量提升,必须先定义class之后才能实例化,不像ES5中可以将构造函数写在实例化之后。
    • ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this

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

    • moduleexportimportES6用来统一前端模块化方案的设计思路和实现方案。exportimport的出现统一了前端模块化的实现方案,整合规范了浏览器/服务端的模块化方法,用来取代传统的AMD/CMDrequireJSseaJScommondJS等等一系列前端模块不同的实现方案,使前端模块化更加统一规范,JS也能更加能实现大型的应用程序开发。
    • import引入的模块是静态加载(编译阶段加载)而不是动态加载(运行时加载)。
    • import引入export导出的接口值是动态绑定关系,即通过该接口,可以取到模块内部实时的值

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

    • 常用箭头函数来取代var self = this;的做法。
    • 常用let取代var命令。
    • 常用数组/对象的结构赋值来命名变量,结构更清晰,语义更明确,可读性更好。
    • 在长字符串多变量组合场合,用模板字符串来取代字符串累加,能取得更好地效果和阅读体验。
    • Class类取代传统的构造函数,来生成实例化对象。
    • 在大型应用开发中,要保持module模块化开发思维,分清模块之间的关系,常用importexport方法。

    22、ES6的了解

    新增模板字符串(为JavaScript提供了简单的字符串插值功能)、箭头函数(操作符左边为输入的参数,而右边则是进行的操作以及返回的值Inputs=>outputs。)、for-of(用来遍历数据—例如数组中的值。)arguments对象可被不定参数和默认参数完美代替。ES6将promise对象纳入规范,提供了原生的Promise对象。增加了let和const命令,用来声明变量。增加了块级作用域。let命令实际上就增加了块级作用域。ES6规定,var命令和function命令声明的全局变量,属于全局对象的属性;let命令、const命令、class命令声明的全局变量,不属于全局对象的属性。。还有就是引入module模块的概念

    23、说说你对Promise的理解

    • 依照 Promise/A+ 的定义,Promise 有四种状态:
      • pending: 初始状态, 非 fulfilled 或 rejected.
      • fulfilled: 成功的操作.
      • rejected: 失败的操作.
      • settled: Promise已被fulfilled或rejected,且不是pending
    • 另外, fulfilled 与 rejected 一起合称 settled
    • Promise 对象用来进行延迟(deferred) 和异步(asynchronous ) 计算

    24、Promise 的构造函数

    • 构造一个 Promise,最基本的用法如下:
    var promise = new Promise(function(resolve, reject) {
    
            if (...) {  // succeed
    
                resolve(result);
    
            } else {   // fails
    
                reject(Error(errMessage));
    
            }
        });
    
    

    Promise 实例拥有 then 方法(具有 then 方法的对象,通常被称为thenable)。它的使用方法如下:

    promise.then(onFulfilled, onRejected)
    
    

    接收两个函数作为参数,一个在 fulfilled 的时候被调用,一个在rejected的时候被调用,接收参数就是 future,onFulfilled 对应 resolve, onRejected 对应 reject

     

    什么是 Promise ?

    • Promise 就是一个对象,用来表示并传递异步操作的最终结果
    • Promise 最主要的交互方式:将回调函数传入 then 方法来获得最终结果或出错原因
    • Promise 代码书写上的表现:以“链式调用”代替回调函数层层嵌套(回调地狱)

     

    解构赋值:
    只要判定了等号两边的模式相同(解构),左边的变量就会被赋予对应的值(赋值),以前一次给一个变量赋值,解构赋值可以一次性给多个变量进行赋值。

     

    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)
         }
         
    
    

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

    • == 相等运算符,比较时会自动进行数据类型转换
    • === 严格相等运算符,比较时不进行隐式类型转换
    • Object.is 同值相等算法,在 === 基础上对 0 和 NaN 特别处理
    +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。
    展开全文
  • title: ES6面试题 date: 2019-10-12 20:23:00 updated: 2019-10-12 20:23:00 tags: ['web前端面试'] ES6面试题 1. promise相关 Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、...
        

    title: ES6面试题
    date: 2019-10-12 20:23:00
    updated: 2019-10-12 20:23:00
    tags: ['web前端面试']


    ES6面试题

    1. promise相关

    Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法

    Promise对象有以下两个特点。

    (1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

    (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

    • 状态可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
      • promise
      • promise 的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
    • then
      • promise 必须实现then方法,而且then必须返回一个 promise ,同一个 promise 的then可以调用多次(链式),并且回调的执行顺序跟它们被定义时的顺序一致
      • then方法接受两个参数,第一个参数是成功时的回调,在 promise 由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在 promise 由“等待”态转换到“拒绝”态时调用
    • 基本用法

      function loadImg(src) {
              var promise = new Promise(function(resolve, reject) {
                  var img = document.createElement('img')
                  img.onload = function () {
                      resolve(img)
                  }
                  img.onerror = function () {
                      reject('图片加载失败')
                  }
                  img.src = src;
              })
              return promise
          }
          
       var src = 'https://csdnimg.cn/cdn/content-toolbar/csdn-logo_.png?v=20190924.1'
          var result = loadImg(src)
          result.then(function(img) {
              console.log(1, img.height);
              return img
          }, function () {
              console.log(2, '2error');
          })
      
    • 如何异常捕获(Error和reject都要考虑)

      function loadImg(src) {
              var promise = new Promise(function(resolve, reject) {
                  var img = document.createElement('img')
                  img.onload = function () {
                      resolve(img)
                  }
                  img.onerror = function () {
                      reject('图片加载失败')
                  }
                  img.src = src;
              })
              return promise
          }
         var src = 'https://csdnimg.cn/cdn/content-toolbar/csdn-logo_.png?v=20190924.1'
          var src = 'https://csdnimg.cn/cdn/content-toolbar/csdn-logo_.png1?v=20190924.1'
          var result = loadImg(src)
          result.then(function(img) {
              console.log(1, img.height);
              return img
          }).then(function(img) {
              console.log(1, img.width);
          }).catch(function (ex) {
              console.log('catch:', ex);
          })
      
    • 多个串联-链式执行好处

        // 串联操作
          var src1 = 'https://csdnimg.cn/cdn/content-toolbar/csdn-logo_.png?v=20190924.1'
          var result1 = loadImg(src1)
          var src2 = 'https://upload.jianshu.io/users/upload_avatars/3680705/53474ecc-5d15-4c80-97cb-558ff676dd52.jpeg?imageMogr2/auto-orient/strip|imageView2/1/w/80/h/80/format/webp'
          var result2 = loadImg(src2)
      
          // 特别注意前一个then的返回值
          result1.then(function(img1) {
              console.log("result1第一个图片加载完毕", img1.width);
              return result2
          }).then(function(img2) {
              console.log("result2第二个图片加载完毕", img2.width);
          }).catch(function (ex) {
              console.log('catch:', ex);
          })
      
    • Promise.all 和 Promise.race

      all的用法
      与then同级的另一个方法,all方法,该方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后并且执行结果都是成功的时候才执行回调。

      race的用法
      all是等所有的异步操作都执行完了再执行then方法,那么race方法就是相反的,谁先执行完成就先执行回调。

      // Promise.all()  和 Promise.race()
          var src1 = 'https://csdnimg.cn/cdn/content-toolbar/csdn-logo_.png?v=20190924.1'
          var result1 = loadImg(src1)
          var src2 = 'https://upload.jianshu.io/users/upload_avatars/3680705/53474ecc-5d15-4c80-97cb-558ff676dd52.jpeg?imageMogr2/auto-orient/strip|imageView2/1/w/80/h/80/format/webp'
          var result2 = loadImg(src2)
          Promise.all([result1, result2]).then(function (datas) {
              console.log('all', datas[0])
              console.log('all', datas[1])
          })
          Promise.race([result1, result2]).then(function (data) {
              console.log('race', data)
          })
      
    • Promise标准-状态变化,then函数

    2. async 和 await

    • 基本语法

       function loadImg(src) {
              var promise = new Promise(function(resolve, reject) {
                  var img = document.createElement('img')
                  img.onload = function () {
                      resolve(img)
                  }
                  img.onerror = function () {
                      reject('图片加载失败')
                  }
                  img.src = src;
              })
              return promise
          }
       // async 和 await
          var asyncLoad = async function() {
              var src1 = 'https://csdnimg.cn/cdn/content-toolbar/csdn-logo_.png?v=20190924.1'
              var src2 = 'https://upload.jianshu.io/users/upload_avatars/3680705/53474ecc-5d15-4c80-97cb-558ff676dd52.jpeg?imageMogr2/auto-orient/strip|imageView2/1/w/80/h/80/format/webp'
              var result1 = await loadImg(src1)    
              var result2 = await loadImg(src2)
          }
      
    • 使用了Promise,并没有和Promise冲突

    • 完全是同步的写法,再也没有回调函数

    • 但是:改变不了js单线程,、异步的本质

    3. class用法

    // es5
    function Animal() {
        this.eat = function() {
            console.log('animal eat')
        }
    }
    function Dog() {
        this.bark = function() {
            console.log('dog bark')
        }
    }
    Dog.prototype = new Animal()
    // 哈士奇
    var hashiqi = new Dog();
    
    // ES6的写法
    class Animal {
        eat () {
            console.log('animal eat')
        }
    }
    
    class Dog extends Animal {
        bark () {
            console.log('dog bark')
        }
    }
    var hashiqi = new Dog();
    

    4. ES6中Class 与 普通构造函数有何区别

    • class本质上是构造函数的语法糖;
    • class在语法上更贴近面向对象的写法;
    • class实现继承更加易读易理解;

    5. ES6中var/let/const的区别

    • let
      • let声明只在他所在的代码域中有效

      • let 不存在变量提升,变量需要先声明然后再使用,否则报错

      • 暂时性死区
        块级作用域内存在let命令,它所声明的变量就绑定在这个区域,不再受外部影响;如下代码:

        var tmp = 123;
        if (true) {
            tmp = 'abc';
            let tmp;
            console.log(tmp); // tmp is not defined
        }
        
      • let 不允许重复声明
        不允许在相同作用域内,重复声明同一个变量。

    • const
      • const 声明一个只读的常量,一旦声明,常量的值就不允许改变。
      • const的作用域与let命令相同;只在声明所在的块级作用域内有效。

    5. const定义的对象属性是否可以改变

    const 指针指向的地址不可以变化,指向地址的内容可以变化。

    6. 箭头函数

    https://www.jianshu.com/p/c1ee12a328d2

    7. ES6新特性

    • 不一样的变量声明:const和let
    • 模板字符串
    • 箭头函数(Arrow Functions)
    • 函数的参数默认值
    • 对象和数组解构
    • Promise
    展开全文
  • ES6面试题总结!

    2020-08-18 14:34:58
    ES6面试题总结! 1.变量 var // 重复声明,函数级 let // 不能重复声明,块级,变量 const // 不能重复声明,块级,常量 2.箭头函数 // a.简写 // ()=>{} // i. 如果只有一个参数,()可以省略 // ii. 如果只有一...
  • ES6面试题--持续更新

    2020-05-27 09:49:37
    ES6面试题汇总ES6的一些特点,新增属性?var、let、const之间的区别?使用箭头函数应注意什么?介绍下 Set、Map的区别?Promise构造函数是同步执行还是异步执行,那么 then 方法呢?promise有几种状态,什么时候会...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,417
精华内容 566
关键字:

es6面试题