共计 5695 个字符,预计需要花费 15 分钟才能阅读完成。
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(); // 空 Map
m.set('Adam', 67); // 增加新的 key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在 key 'Adam': true
m.get('Adam'); // 67
m.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(); // 空 Set
var 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 defined
let 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)); // 11
console.log(obj2.c(1)); // 11
(5). 箭头函数没有原型属性
var a = ()=>{return 1;}
function b(){return 2;}
console.log(a.prototype); // undefined
console.log(b.prototype); // {constructor: ƒ}
(6). 箭头函数不能作为 Generator 函数,不能应用 yield 关键字
(7). 箭头函数返回对象时,要加一个小括号
var func = () => ({ foo: 1}); // 正确
var func = () => { foo: 1}; // 谬误
(8). 箭头函数在 ES6 class 中申明的办法为实例办法,不是原型办法
//deom1
class 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 办法
//demo2
class 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 图标。