Map、Set

参考https://www.runoob.com/w3cnot...
Map
Map是一组键值对的构造,具备极快的查找速度。
举个例子,假如要依据同学的名字查找对应的问题,如果用Array实现,须要两个Array:

var names = ['Michael', 'Bob', 'Tracy'];var scores = [95, 75, 85];

给定一个名字,要查找对应的问题,就先要在names中找到对应的地位,再从scores取出对应的问题,Array越长,耗时越长。
如果用Map实现,只须要一个“名字”-“问题”的对照表,间接依据名字查找问题,无论这个表有多大,查找速度都不会变慢。用JavaScript写一个Map如下:

var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);m.get('Michael'); // 95

初始化Map须要一个二维数组,或者间接初始化一个空Map。Map具备以下办法:

var m = new Map(); // 空Mapm.set('Adam', 67); // 增加新的key-valuem.set('Bob', 59);m.has('Adam'); // 是否存在key 'Adam': truem.get('Adam'); // 67m.delete('Adam'); // 删除key 'Adam'm.get('Adam'); // undefined因为一个key只能对应一个value,所以,屡次对一个key放入value,前面的值会把后面的值冲掉:var m = new Map();m.set('Adam', 67);m.set('Adam', 88);m.get('Adam'); // 88

Set
Set和Map相似,也是一组key的汇合,但不存储value。因为key不能反复,所以,在Set中,没有反复的key。
要创立一个Set,须要提供一个Array作为输出,或者间接创立一个空Set:

var s1 = new Set(); // 空Setvar s2 = new Set([1, 2, 3]); // 含1, 2, 3

反复元素在Set中主动被过滤:

var s = new Set([1, 2, 3, 3, '3']);s; // Set {1, 2, 3, "3"}

留神数字3和字符串'3'是不同的元素。
通过add(key)办法能够增加元素到Set中,能够反复增加,但不会有成果:

s.add(4);s; // Set {1, 2, 3, 4}s.add(4);s; // 依然是 Set {1, 2, 3, 4}

通过delete(key)办法能够删除元素:

var s = new Set([1, 2, 3]);s; // Set {1, 2, 3}s.delete(3);s; // Set {1, 2}

Maps 和 Objects 的区别?

一个 Object 的键只能是字符串或者 Symbols,但一个 Map 的键能够是任意值。

Map 中的键值是有序的(FIFO 准则),而增加到对象中的键则不是。

Map 的键值对个数能够从 size 属性获取,而 Object 的键值对个数只能手动计算。

Object 都有本人的原型,原型链上的键名有可能和你本人在对象上的设置的键名产生抵触。

for in 、for of区别?

例一:

   const obj = {        a: 1,        b: 2,        c: 3    }    for (let i in obj) {        console.log(i) // a、 b、c     }    for (let i of obj) {        console.log(i)// Uncaught TypeError: obj is not iterable 报错了    }

例二:

    const arr = ['a', 'b', 'c']    // for in 循环    for (let i in arr) {        console.log(i)//0,1,2 返回的数据下标    }    // for of    for (let i of arr) {        console.log(i)//a,b,c    }

例三:

    const arr = ['a', 'b']    // 手动给 arr数组增加一个属性    arr.name = 'qiqingfu'    // for in 循环能够遍历出 name 这个键名    for (let i in arr) {        console.log(i) // a,b,name     }    for (let i of arr) {        console.log(i)//a,b    }

联合下面的例子,剖析得出:
for...in 语句用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。
for in失去对对象的key或数组,字符串的下标
for of和forEach一样,是间接失去值
for of不能对象,会报错
简略说,for in是遍历键名,for of是遍历键值。

var let const的区别?

 var申明变量能够反复申明,而let不能够反复申明 var是不受限于块级的,而let是受限于块级 var会与window相映射(会挂一个属性),而let不与window相映射 var能够在申明的下面拜访变量,而let有暂存死区,在申明的下面拜访变量会报错 const申明之后必须赋值,否则会报错 const定义不可变的量,扭转了就会报错 const和let一样不会与window相映射、反对块级作用域、在申明的下面拜访变量会报错  

箭头函数的了解?

1、箭头函数根本模式

let func = (num) => num;let func = () => num;let sum = (num1,num2) => num1 + num2;[1,2,3].map(x => x * x);

2、箭头函数根本特点

(1). 箭头函数this为父作用域的this,不是调用时的this
箭头函数的this永远指向其父作用域,任何办法都扭转不了,包含call,apply,bind。
一般函数的this指向调用它的那个对象。

let person = {    name:'jike',    init:function(){        //为body增加一个点击事件,看看这个点击后的this属性有什么不同        document.body.onclick = ()=>{            alert(this.name);//?? this在浏览器默认是调用时的对象,可变的?                          }    }}person.init();

上例中,init是function,以person.init调用,其外部this就是person自身,而onclick回调是箭头函数,
其外部的this,就是父作用域的this,就是person,能失去name。

let person = {    name:'jike',    init:()=>{        //为body增加一个点击事件,看看这个点击后的this属性有什么不同        document.body.onclick = ()=>{            alert(this.name);//?? this在浏览器默认是调用时的对象,可变的?                          }    }}person.init();

上例中,init为箭头函数,其外部的this为全局window,onclick的this也就是init函数的this,也是window,
失去的this.name就为undefined。

(2). 箭头函数不能作为构造函数,不能应用new

//构造函数如下:function Person(p){    this.name = p.name;}//如果用箭头函数作为构造函数,则如下var Person = (p) => {    this.name = p.name;}

因为this必须是对象实例,而箭头函数是没有实例的,此处的this指向别处,不能产生person实例,自圆其说。

(3). 箭头函数没有arguments,caller,callee

箭头函数自身没有arguments,如果箭头函数在一个function外部,它会将内部函数的arguments拿过去应用。
箭头函数中要想接管不定参数,应该应用rest参数...解决。

let B = (b)=>{  console.log(arguments);}B(2,92,32,32);   // Uncaught ReferenceError: arguments is not definedlet C = (...c) => {  console.log(c);}C(3,82,32,11323);  // [3, 82, 32, 11323]

(4). 箭头函数通过call和apply调用,不会扭转this指向,只会传入参数

let obj2 = {    a: 10,    b: function(n) {        let f = (n) => n + this.a;        return f(n);    },    c: function(n) {        let f = (n) => n + this.a;        let m = {            a: 20        };        return f.call(m,n);    }};console.log(obj2.b(1));  // 11console.log(obj2.c(1)); // 11

(5). 箭头函数没有原型属性

var a = ()=>{  return 1;}function b(){  return 2;}console.log(a.prototype);  // undefinedconsole.log(b.prototype);   // {constructor: ƒ}

(6). 箭头函数不能作为Generator函数,不能应用yield关键字

(7). 箭头函数返回对象时,要加一个小括号

var func = () => ({ foo: 1 }); //正确var func = () => { foo: 1 };   //谬误

(8). 箭头函数在ES6 class中申明的办法为实例办法,不是原型办法

//deom1class Super{    sayName(){        //do some thing here    }}//通过Super.prototype能够拜访到sayName办法,这种模式定义的办法,都是定义在prototype上var a = new Super()var b = new Super()a.sayName === b.sayName //true//所有实例化之后的对象共享prototypy上的sayName办法//demo2class Super{    sayName =()=>{        //do some thing here    }}//通过Super.prototype拜访不到sayName办法,该办法没有定义在prototype上var a = new Super()var b = new Super()a.sayName === b.sayName //false//实例化之后的对象各自领有本人的sayName办法,比demo1须要更多的内存空间

因而,在class中尽量少用箭头函数申明办法。

(9). 多重箭头函数就是一个高阶函数,相当于内嵌函数

const add = x => y => y + x;//相当于function add(x){  return function(y){    return y + x;  };}

(10). 箭头函数常见谬误

let a = {  foo: 1,  bar: () => console.log(this.foo)}a.bar()  //undefined

bar函数中的this指向父作用域,而a对象没有作用域,因而this不是a,打印后果为undefined

function A() {  this.foo = 1}A.prototype.bar = () => console.log(this.foo)let a = new A()a.bar()  //undefined

原型上应用箭头函数,this指向是其父作用域,并不是对象a,因而得不到预期后果

一般函数和箭头函数区别?

//箭头函数let fun = () => {    console.log('lalalala');}//一般函数function fun() {    console.log('lalla');}

应用箭头函数应留神什么?

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

对于then()办法的了解

then()只有在Promise对象中才有。
1.then()办法是异步执行
2.意思是:就是当then()前的办法执行实现后在执行then()外部的程序,这样就防止了,数据没获取到等的问题。
3.语法:promise.then(onCompleted,onRejected);
4.参数

1.必须。(promise)    Promise对象2.必须。(onCompleted)    承诺胜利实现时要运行的履行处理程序函数3.可选。(onRejected)    承诺被回绝时要运行的谬误处理程序函数

promise原理实现

1、最简略的实现
基于下面的利用场景发现promise能够又三种状态,别离是pedding、Fulfilled、Rejected.

pedding Promise对象实例创立时候的初始状态Fulfilled能够了解为胜利的状态Rejected能够了解为失败的装填

Promise.all能够将多个Promise实例包装成一个新的Promise实例。同时,胜利和失败的返回值是不同的,胜利的时候返回的是一个后果数组,而失败的时候则返回最先被reject失败状态的值。
具体代码如下:

let p1 = new Promise((resolve,reject)=>{   resolve('胜利了')})let p2 = new Promise((resolve,reject)=>{   resolve('success')}) let p3 = Promise.reject('失败')Promise.all([p1,p2]).then((result)=>{   console.log(result) //['胜利了','success']}).catch((error)=>{   console.log(error)})Promise.all([p1,p3,p2]).then((result)=>{   console.log(result) }).catch((error)=>{   console.log(error)  //失败了,打出'失败'})

Promise.all在解决多个异步解决时十分有用,比如说一个页面上须要等两个或多个ajax的数据回来当前才失常显示,在此之前只显示loading图标。