ES6面试题大全

以下题目是根据网上多份面经收集而来的,题目相同意味着被问的频率比较高,有问题欢迎留言讨论,喜欢可以点赞关注。

image.png
1.let const var比较区别,ES6中let块作用域是怎么实现的

https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/133

先说说这三者的区别吧:

可以结合https://www.jianshu.com/p/47b49d7bdfc2中的第一节来看。

(一)var

  • var 命令会发生“变量提升”现象,即变量可以在声明之前使用,值为 undefined
  • 内层变量可能覆盖外层变量
  • 用来计数的循环变量泄露为全局变量

(二)let

  • 声明的全局变量不会挂在顶层对象下面
  • 所声明的变量一定要在声明后使用,否则报错,报错 ReferenceError
  • 暂时性死区,只要块级作用域内存在 let 命令,它所声明的变量就“绑定”( binding )这个区域,不再受外部的影响,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。
  • 不允许重复声明

(三)const

  • 声明的全局变量不会挂在顶层对象下面
  • const 声明之后必须马上赋值,否则会报错
  • const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。
  • const 一旦声明变量,就必须立即初始化,不能留到以后赋值。
  • const 命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用

如 const 声明了一个复合类型的常量,其存储的是一个引用地址,不允许改变的是这个地址,而对象本身是可变的。

//      const arr 数组可以赋值
        const arr = ['apple', 'banana']
        arr.push('orange')
        console.log(arr)//["apple", "banana", "orange"]
然后是原理,原理确实没认真研究过,在网上翻了一番资料,结合自己的理解简单说下(纯属个人愚见,高手轻喷)

变量与内存之间的关系,主要由三个部分组成:

  1. 变量名
  2. 内存地址
  3. 内存空间

JS 引擎在读取变量时,先找到变量绑定的内存地址,然后找到地址所指向的内存空间,最后读取其中的内容。当变量改变时,JS 引擎不会用新值覆盖之前旧值的内存空间(虽然从写代码的角度来看,确实像是被覆盖掉了),而是重新分配一个新的内存空间来存储新值,并将新的内存地址与变量进行绑定,JS 引擎会在合适的时机进行 GC,回收旧的内存空间。

const 定义变量(常量)后,变量名与内存地址之间建立了一种不可变的绑定关系,阻隔变量地址被改变,当 const 定义的变量进行重新赋值时,根据前面的论述,JS 引擎会尝试重新分配新的内存空间,所以会被拒绝,便会抛出异常。

var的话会直接在栈内存里预分配内存空间,然后等到实际语句执行的时候,再存储对应的变量,如果传的是引用类型,那么会在堆内存里开辟一个内存空间存储实际内容,栈内存会存储一个指向堆内存的指针

ES6中let块作用域是怎么实现的

let的话,是不会在栈内存里预分配内存空间,而且在栈内存分配变量时,做一个检查,如果已经有相同变量名存在就会报错。也就是暂时性死区,只要块级作用域内存在 let 命令,它所声明的变量就“绑定”( binding )这个区域,不再受外部的影响,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。

const的话,也不会预分配内存空间,在栈内存分配变量时也会做同样的检查。不过const存储的变量是不可修改的,对于基本类型来说你无法修改定义的值,对于引用类型来说你无法修改栈内存里分配的指针,但是你可以修改指针指向的对象里面的属性

2.反引号(`)标识(模板字符串)

https://blog.csdn.net/zwt_guiji/article/details/81979299

模板字符串是在ES6中兴起

用法

// 普通字符串
`In JavaScript '\n' is a line-feed.` 
// 多行字符串
`In JavaScript this 
isnot legal.`
// 字符串中嵌入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?` // Hello Bob, how are you today?

模板字符串都是用反引号表示,如果在模板字符串中需要使用反引号,则前面需要用反斜杠转义。

如果使用模板字符串表示多行字符串,则所有的空格、缩进和换行都会被保留在输出中。比如<ul>标签前面会有一个换行。如果想把行首和行尾的换行、空格等去掉,则使用trim方法即可。

模板字符串中嵌入变量,要将变量名写在${}之中。大括号内可以放入任意的JavaScript表达式,可以进行运算,以及引入对象属性。

模板字符串之中还可以调用函数。

如果大括号中的值不是字符串,则将按照一般的规则转换为字符串。如,若大括号中是一个对象,则将默认调用对象的toString方法,把对象转换为字符串。

如果模板字符串中的变量没有声明,则会报错。

// 变量place没有声明
var msg = `Hello, ${place}`;
// ReferenceError: place is not defined

模板字符串之间还可以进行嵌套。

标签模板

模板字符串的功能,不仅是上面那些,它还可以紧跟在一个函数后面,该函数将被调用来处理这个模板字符串,这种称为“标签模板”功能(Tagged template)。

alert`123`// 等同于alert(123)

标签模板其它是一种特殊的函数调用形式,“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。

var a = 1,    b = 2;
 tag`Helo ${a + b} world ${a * b}`;

上面代码中,模板字符串前面有一个标识名tag,它是一个函数。整个表达式的返回值就是tag函数处理模板字符串后的返回值。

函数tag依次会接收到多个参数。

tag函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分,也就是说,变量替换只发生在数组的第一个成员与第二个成员之间、第二个成员与第三个成员之间,以此类推。tag函数的其他参数,都是模板字符串各个变量被替换的值。本例中,模板字符串含有两个变量,因此tag会接收到value1和value2两个参数。

tag函数所有参数的实际值如下:

  • 第一个参数: [‘Hello ‘, ’ world’, ”]
  • 第二个参数: 3
  • 第三个参数: 2

也就是说,tag函数实际上是用下面的形式调用:

tag(['Hello ',' world', ''], 3, 2);

String对象的raw方法

String.raw方法用来充当模板字符串的处理函数,返回一个除表达式和变量会被替换,其它都保持原样的字符串。

String.raw方法可以作为处理模板字符串的基本方法,它会将所有变量替换,而且对斜杠进行转义,方便下一步作为字符串来使用。

3.函数默认参数和剩余(rest)参数

详细解析点击链接

    1. 函数默认参数
        function show({x=0,y=0}={}){
            console.log(x,y);
        }
        show()
    2. 函数参数默认已经定义了,不能再使用let,const声明
        function show(a=18){
            let a = 101;  //错误
            console.log(a);
        }
        show()

扩展运算符、Reset运算符:
    ...

    展开数组

    ... :
        [1,2,3,4]  -> ... [1,2,3,4]  ->  1,2,3,4,5
    ...:
        1,2,3,4,5  -> ...1,2,3,4,5  ->  [1,2,3,4,5]

    剩余参数: 必须放到最后

rest参数和 arguments对象的区别

image.png

4.箭头函数this指向问题,箭头函数与普通函数的区别,你说箭头函数没有自己的this,那(()=>{}).bind(this)可以么?

https://juejin.im/post/5b14d0b4f265da6e60393680

image.png

六没
1、没有this
箭头函数没有 this,所以需要通过查找作用域链来确定 this 的值。这就意味着如果箭头函数被非箭头函数包含,this 绑定的就是最近一层非箭头函数的 this。,因为箭头函数没有 this,所以也不能用 call()、apply()、bind() 这些方法改变 this 的指向,可以看一个例子:

var value = 1;
var result = (() => this.value).bind({value: 2})();
console.log(result); // 1

2、没有arguments
箭头函数没有自己的 arguments 对象,这不一定是件坏事,因为箭头函数可以访问外围函数的。通过命名参数或者 rest 参数的形式访问参数

3、没有new关键字调用
箭头不能被用作构造函数,如果通过 new 的方式调用,会报错

var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

4、没有new.target
因为不能使用 new 调用,所以也没有 new.target 值。关于 new.target,可以参考 es6.ruanyifeng.com/#docs/class…

5、没有原型
由于不能使用 new 调用箭头函数,所以也没有构建原型的需求,于是箭头函数也不存在 prototype 这个属性。

var Foo = () => {};
console.log(Foo.prototype); // undefined

6、没有super
连原型都没有,自然也不能通过 super 来访问原型的属性,所以箭头函数也是没有 super 的,不过跟 this、arguments、new.target 一样,这些值由外围最近一层非箭头函数决定。

5.属性简写

1.对象的方法简写

const o = {
  method() {
    return "Hello!";
  }
};

// 等同于

const o = {
  method: function() {
    return "Hello!";
  }
};

let birth = '2000/01/01';
const Person = {
  name: '张三',
  //等同于birth: birth
  birth,
  // 等同于hello: function ()...
  hello() { console.log('我的名字是', this.name); }
};
2.对象的属性简写

const a= 'a';
const b= {a};                    
b// {a: "a"}
// 等同于
const b= {a: a};             //前面的a是对象属性的名字,后面的a代表变量a

实际应用:
function f(x, y) {
  return {x, y};
}

// 等同于

function f(x, y) {
  return {x: x, y: y};
}

f(1, 2) // {x: 1, y: 2}
3.扩展


import App from './App.vue'
new Vue({
   router,
   store,
   render: h => h(App)
 })

等同于

new Vue({
  router:router,
  store:store,
  render:function(h){
      return  h(App);
  }
})
6.方法简写

同上

7.Object.keys()方法,获取对象的所有属性名或方法名

一、语法

Object.keys(obj)
参数:要返回其枚举自身属性的对象
返回值:一个表示给定对象的所有可枚举属性的字符串数组

二、处理对象,返回可枚举的属性数组

let person = {name:"张三",age:25,address:"深圳",getName:function(){}}
Object.keys(person) // ["name", "age", "address","getName"]
image

三、处理数组,返回索引值数组

let arr = [1,2,3,4,5,6]
Object.keys(arr) // ["0", "1", "2", "3", "4", "5"]
image

四、处理字符串,返回索引值数组

let str = "saasd字符串"
Object.keys(str) // ["0", "1", "2", "3", "4", "5", "6", "7"]
image

五、常用技巧

let person = {name:"张三",age:25,address:"深圳",getName:function(){}}
Object.keys(person).map((key)=>{
person[key] // 获取到属性对应的值,做一些处理
}) 

六、Object.values()和Object.keys()是相反的操作,把一个对象的值转换为数组

8.Object.assign ()原对象的属性和方法都合并到了目标对象

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

    Object.assign():   用来合并对象
    let 新的对象 = Object.assign(目标对象, source1, srouce2....)

    function ajax(options){  //用户传
        let defaults={
            type:'get',
            header:
            data:{}
            ....
        };

        let json = Object.assign({}, defaults, options);
        .....
    }
    
    用途:
        1. 复制一个对象
        2. 合并参数

    let json = { a: 3, b: 4 };
    let json2 = { ...json };
    console.log(json2 === json)//false
    console.log(Object.assign({}, json) === json)//false
    console.log(Object.assign(json) === json)//true

注意:
1.如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性
2.Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标
对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如
果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到
原型,应使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。

9.for...of 循环

https://www.jianshu.com/p/2e6dd8906e97

一个数据结构只要部署了Symbol.iterator属性,就被视为具有 iterator 接口,就可以用for...of循环遍历它的成员。也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、Generator 对象,以及字符串。

for...of 遍历 非 Iterator 的类数组对象

并不是所有类似数组的对象都具有 Iterator 接口,一个简便的解决方法,就是使用Array.from方法将其转为数组。

let arrayLike = { length: 2, 0: 'a', 1: 'b' };

// 报错
for (let x of arrayLike) {
  console.log(x);
}

// 正确
for (let x of Array.from(arrayLike)) {
  console.log(x);
}

for...of 遍历 对象
对于普通的对象,for...of结构不能直接使用,会报错。使用 for...in 可以遍历对象的键名。

let obj = {
    a: 1,
    b: 2,
    c: 3
}

for (let e in obj) {
    console.log(e);  // 'a'  'b'  'c'
}

总之,for...in循环主要是为遍历对象而设计的,不适用于遍历数组。

一种解决方法是,使用Object.keys方法将对象的键名生成一个数组,然后再用 for...of 遍历这个数组。

for(let key of Object.keys(obj)) {
    console.log(key + ': ' + obj[key]);
}

另一个方法是使用 Generator 函数将对象重新包装一下。

function* entries(obj) {
    for(let key of Object.keys(obj)) {
        yield [key, obj[key]];
    }
}
for(let [key, value] of entries(obj)) {
    console.log(key, '->', value);
}

9、for...of 可以与 break / continue / return 配合使用

for (var n of arr) {
    if (n > 10) {
        break;
    }
    console.log(n);
}
10.import和export,CommonJS 中的 require/exports 和 ES6 中的 import/export 区别?

1、CommonJS模块输出的是一个值的拷贝,一旦输出一个值,模块内部的变化就影响不到这个值。

  ES6模块输出的是值的引用,JS引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,在根据引用到被加载的那个模块里面去取值。ES6模块是动态引用,并且不会缓存运行结果,而是动态的去被加载的模块取值,模块里面的变量绑定其所在的模块。

2、CommonJS模块是运行时加载,ES6模块是编译时输出接口(ES6可以在编译时就完成模块加载,效率要比CommonJS模块的加载方式高)。

  1. ES6模块是通用的,同一个模块不用修改,就可以用在浏览器

4、require/exports是CommonJS在Node中实现的。

  import/export是ES6的模块,对ES6只要使用babel就可以了

5、ES6模块的设计思想,是尽量静态化,使得编译时就能确定模块的依赖关系以及输入和输出的变量。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

12.解构赋值

非常有用,特别在做数据交互 ajax

let [a,b,c] =[12,5, 6];

注意: 左右两边,结构格式要保持一致

        // let [a, b, c] = [12, 3, 'k']
        // console.log(a, b, c)//12 3 "k"

        // 属性名称要一一对应
        // let { name, age, job, f, arr } = {
        //     name: 'Strive',
        //     age: 18,
        //     job: '码畜',
        //     arr: [
        //         { name: 'liu' },
        //         { name: 'zhao' }
        //     ]
        // };
        // console.log(name, age, job, f)//Strive 18 码畜 undefined
        // console.log(name, age, job, arr)//Strive 18 码畜 (2) [{…}, {…}]

        // let json = {
        //     name: 'Strive',
        //     age: 18,
        //     job: '码畜',
        //     arr: [
        //         { name: 'liu' },
        //         { name: 'zhao' }
        //     ]
        // };
        // let { name: n, age: g, job: f, arr } = json;
        // console.log(n, g, f, arr)//Strive 18 码畜 (2) [{…}, {…}]

        // let [a, b, c] = ['a', 'b']
        // console.log(a, b, c)//a b undefined

        // 传undefined和上面不传参数是一样的 传null和‘’都是有值
        // let [a, b, c] = ['a', 'b', undefined]
        // console.log(a, b, c)//a b undefined

        // let [a, b, c = 'no-data'] = ['a', 'b']
        // console.log(a, b, c)//a b no-data

        // let a;
        // //先用let定义没有赋值  要用小括号括起来  不然大括号直接暴露在外面  会起到块级作用域的
        // ({ a } = { a: 'apple', b: 'banana' });
        // console.log(a)

        // a,b相互赋值 不用找中间值
        // let a = 12;
        // let b = 10;
        // [a, b] = [b, a]
        // console.log(a)//10

        // function fn() {
        //     return {
        //         leftVal: 10,
        //         topVal: 20
        //     }
        // }

        // let { leftVal, topVal: t } = fn();
        // console.log(leftVal, t)//10 20

        function fn({ a, b = '默认值' }) {
            console.log(a)//1
        }
        fn({
            a: 1,
            b: undefined
        })
13.set数据结构(可用于快速去重)
set数据结构:
    类似数组,但是里面不能有重复值

let arr  = ['a','b','a'];

let arr = new Array();

set用法:
    let setArr = new Set(['a','b']);

    setArr.add('a');   往setArr里面添加一项
    setArr.delete('b'); 删除一项
    setArr.has('a') 判断setArr里面有没有此值
    setArr.size 个数

    setArr.clear(); 清空

14.Spread Operator 展开运算符(...)
... [1,2,3,4]  ->  1,2,3,4,5
... 1,2,3,4,5  ->  [1,2,3,4,5]
15.字符串新增方法

https://www.cnblogs.com/weimingmei/p/11488458.html
1、String.fromCodePoint()
2、String.raw()
3、codePointAt()
4、normalize()
5、includes(), startsWith(), endsWith()
6、repeat()
7、padStart(),padEnd()
8、trimStart(),trimEnd()
9、matchAll()

关于字符串一些东西:
字符串查找:
        str.indexOf(要找的东西)   返回索引(位置) ,没找到返回-1
        str.includes(要找的东西)   返回值  true/false

        判断浏览器:  includes

        http://www.xxx.xx

        字符串是否以谁开头:
            str.startsWith(检测东西)

            检测地址
        字符串是否以谁结尾:
            str.endsWith(检测东西)

            .png

        重复字符串:
            str.repeat(次数);
填充字符串:
        str.padStart(整个字符串长度, 填充东西)   往前填充
        str.padEnd(整个字符串长度, 填充东西)    往后填充

        str.padStart(str.length+padStr.length, padStr)
16.声明类与继承:class、extend,ES6 class与ES5 function区别及联系
image.png

区别
https://blog.csdn.net/u012657197/article/details/77542404

17.symbol应用
数据类型:
    number、string、boolean、Object、undefined、function

    用typeof检测出来数据类型: symbol

    new Number(12)
    new String()
    new Array()

symbol  使用情况一般

定义:
    let syml = Symbol('aaa');

注意:
1. Symbol 不能new
2. Symbol() 返回是一个唯一值坊间传说, 做一个key,定义一些唯一或者私有一些东
3. symbol是一个单独数据类型,就叫 symbol, 基本类型
4. 如果symbol作为key,用for in循环,出不来
5.Symbol值作为对象属性时,不能使用点运算符。


json  ->  for in
18.es6和es7中新增加了什么

ES2016(es7)添加了两个小的特性来说明标准化过程:
数组includes()方法,用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回true,否则返回false。
a ** b指数运算符,它与 Math.pow(a, b)相同。


image.png
19.ES6怎么编译成ES5,css-loader原理,过程

Babel 是一个 JavaScript 编译器,Babel 是一个工具链,主要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。Webpack也有自动编译转换能力。
①引入脚本babel库②如下

image.png

css-loader原理,过程
loader 用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。css-loader是分析各个css文件的关系并合并成一个css。
关于es6及以上的js编译成es5

20.ES6转成ES5的常见例子

https://www.cnblogs.com/slongs/p/11238574.html

21.使用解构,实现两个变量的值的交换
let [a,b]=[b,a]
22.利用数组推导,计算出数组 [1,2,3,4] 每一个元素的平方并组成新的数组
    var arr1 = [1, 2, 3, 4];
    var arr2 = arr1.map(i => i * i)
    console.log(arr2);
23.map和set有没有用过,如何实现一个数组去重,map数据结构有什么优点?ES6的Set内部实现

Map 对象
Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。

Maps 和 Objects 的区别

1、一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键可以是任意值。
2、Map 中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
3、Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
4、Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

for…of

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
 
// 将会显示两个 log。 一个是 "0 = zero" 另一个是 "1 = one"
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
/* 这个 entries 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的 [key, value] 数组。 */
 
// 将会显示两个log。 一个是 "0" 另一个是 "1"
for (var key of myMap.keys()) {
  console.log(key);
}
/* 这个 keys 方法返回一个新的 Iterator 对象, 它按插入顺序包含了 Map 对象中每个元素的键。 */
 
// 将会显示两个log。 一个是 "zero" 另一个是 "one"
for (var value of myMap.values()) {
  console.log(value);
}
/* 这个 values 方法返回一个新的 Iterator 对象,它按插入顺序包含了 Map 对象中每个元素的值。 */

forEach()

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
 
// 将会显示两个 logs。 一个是 "0 = zero" 另一个是 "1 = one"
myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)

Map 与 Array的转换

var kvArray = [["key1", "value1"], ["key2", "value2"]];
 
// Map 构造函数可以将一个 二维 键值对数组转换成一个 Map 对象
var myMap = new Map(kvArray);
 
// 使用 Array.from 函数可以将一个 Map 对象转换成一个二维键值对数组
var outArray = Array.from(myMap);

Set 对象
Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。

Set 中的特殊值
Set 对象存储的值总是唯一的,所以需要判断两个值是否恒等。有几个特殊值需要特殊对待:

+0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复;
undefined 与 undefined 是恒等的,所以不重复;
NaN 与 NaN 是不恒等的,但是在 Set 中只能存一个,不重复。
let mySet = new Set();

mySet.add(1); // Set(1) {1}
mySet.add(5); // Set(2) {1, 5}
mySet.add(5); // Set(2) {1, 5} 这里体现了值的唯一性
mySet.add("some text"); 
// Set(3) {1, 5, "some text"} 这里体现了类型的多样性
var o = {a: 1, b: 2}; 
mySet.add(o);
mySet.add({a: 1, b: 2}); 
// Set(5) {1, 5, "some text", {…}, {…}} 
// 这里体现了对象之间引用不同不恒等,即使值相同,Set 也能存储

类型转换

// Array 转 Set
var mySet = new Set([“value1”, “value2”, “value3”]);
// 用…操作符,将 Set 转 Array
var myArray = […mySet];
String
// String 转 Set
var mySet = new Set('hello'); // Set(4) {"h", "e", "l", "o"}
// 注:Set 中 toString 方法是不能将 Set 转换成 String

数组去重

var mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]

map优点
Map保存[key-value]值,value可多值。

ES6的Set内部实现
https://www.cnblogs.com/hui-fly/p/9459152.html

24.取数组的最大值(ES5、ES6)
// ES5 的写法
Math.max.apply(null, [14, 3, 77, 30]);
 
// ES6 的写法
Math.max(...[14, 3, 77, 30]);
 
// reduce
[14,3,77,30].reduce((accumulator, currentValue)=>{
    return accumulator = accumulator > currentValue ? accumulator : currentValue
});
25.const obj 的属性如何不可变

const定义的基本数据类型的变量确实不能修改。
因为对象是引用类型的,保存的仅是对象的指针,这就意味着,const仅保证指针不发生改变,修改对象的属性不会改变对象的指针,所以是被允许的。也就是说const定义的引用类型只要指针不发生改变,其他的不论如何改变都是允许的。我们试着修改一下指针,让P指向一个新对象,结果如下图:

image

即使对象的内容没发生改变,指针改变也是不允许的。

26.ES6新的特性有哪些?x4

1、let const命令
2、解构赋值
3、字符串方法模板字符串
4、默认函数、剩余函数、箭头函数
5、Symbol
6、Set和Map
7、模块化
8、promise
9、class继承
10、数组的扩展

27.Promise对象
image.png
28.用es6 promise实现封装XMLHttpRequest

只需创建一个Promise对象,调用它的resolve()和reject()以及then()方法,then()里面也可以写箭头函数;

function verifyIdCard(idCardOptions) {
    let options = {
        // url: config.idCardKey.idCardHost + '?idCard=' + idCardOptions.idCard + '&name=' + idCardOptions.name,
        url: 'https://idcert.market.alicloudapi.com/idcard',
        method: 'GET', 
        qs: {
            idCard: idCardOptions.idCard,
            name: idCardOptions.name
        },
        headers: { 
            'cache-control': 'no-cache',
            Authorization: 'APPCODE ' + config.idCardKey.idCardAppCode,
            'Content-Type': 'application/json'
        },
        json: true
    };

    console.info(options)
    return new Promise((resolve, reject) => {
        request(options, (error, response, body) => {
            if (!error && (response.statusCode === 200 || response.statusCode === 304)) {
                let IdCardInfo = {
                    reqInfo: idCardOptions,
                    resInfo: body
                }
                console.info(IdCardInfo)
                let idCardModel = new IdCardModel(IdCardInfo);
                idCardModel.save();
                resolve(body);
            } else {
                reject(error);
            }
        })
    })
}

29.generator(异步编程、yield、next()、await 、async)

Generator 函数,可以通过 yield 关键字,把函数的执行流挂起,为改变执行流程提供了可能,从而为异步编程提供解决方案。Generator 有两个区分于普通函数的部分:一是在 function 后面,函数名之前有个 * ;函数内部有 yield 表达式。其中 * 用来表示函数为 Generator 函数,yield 用来定义函数内部的状态。

function* sendParameter(){
    console.log("strat");
    var x = yield '2';
    console.log("one:" + x);
    var y = yield '3';
    console.log("two:" + y);
    console.log("total:" + (x + y));
}

var sendp1 = sendParameter();
sendp1.next();
// strat
// {value: "2", done: false}
sendp1.next();
// one:undefined
// {value: "3", done: false}
sendp1.next();
// two:undefined
// total:NaN
// {value: undefined, done: true}
var sendp2 = sendParameter();
sendp2.next(10);
// strat
// {value: "2", done: false}
sendp2.next(20);
// one:20
// {value: "3", done: false}
sendp2.next(30);
// two:30
// total:50
// {value: undefined, done: true}
}

一般情况下,next 方法不传入参数的时候,yield 表达式的返回值是 undefined 。当 next 传入参数的时候,该参数会作为上一步yield的返回值。yield* 表达式表示 yield 返回一个遍历器对象,用于在 Generator 函数内部,调用另一个 Generator 函数。

async
async 是 ES7 才有的与异步操作有关的关键字,和 Promise , Generator 有很大关联的。async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。

async function helloAsync(){
    return "helloAsync";
  }
  
console.log(helloAsync())  // Promise {<resolved>: "helloAsync"}
 
helloAsync().then(v=>{
   console.log(v);         // helloAsync
})

await
await 操作符用于等待一个 Promise 对象, 它只能在异步函数 async function 内部使用。返回 Promise 对象的处理结果。如果等待的不是 Promise 对象,则返回该值本身。如果一个 Promise 被传递给一个 await 操作符,await 将等待 Promise 正常处理完成并返回其处理结果。

function testAwait (x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}
 
async function helloAsync() {
  var x = await testAwait ("hello world");
  console.log(x); 
}
helloAsync ();
// hello world

正常情况下,await 命令后面是一个 Promise 对象,它也可以跟其他值,如字符串,布尔值,数值以及普通函数。await针对所跟不同表达式的处理方式:Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。非 Promise 对象:直接返回对应的值。


image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容