第一次写知识点,如有写不好的地方欢迎指出,也可以当作面试的知识点,我知道写的不好,以后会越写越好的。哈哈哈哈哈哈哈
1. var、let、const之间的区别
- var:
- 存在变量提升
- 顶层对象,指向的是window对象
- 可以重复声明一个变量
- let:
- 有块级作用域
- 不存在变量提升
- 一个变量只能声明一次
- const:
- let 有的同样也有
- 声明一个常量,常量并不能改变
- 一旦声明必须赋值
- 声明一个复杂类型,变量指向的是这个内存地址,不能修改这个内存地址
// const 声明复杂类型时
const obj = {};
// 可以
obj.prop = 123;
//不可以
obj = {
prop: 123
}
2. Symbol是什么?
Symbol 是ES6新增的一种基本类型,表示独一无二的值。
let str = Symbol('abc');
let str1 = Symbol('abc');
str === str1 // false
3. 数组新增了哪些方法?
- from()
- 将类数组和可遍历(iterable)的对象转化为数组
- of()
- 将一组值转为数组
- 只有当参数个数不少于2个时,才返回新的数组
- 只有一个参数时,为数组的长度
- fill()
- 填充数组
- find()
- 用于找出第一个符合条件的数组成员。
- findIndex()
- 和find类似,返回第一个符合条件的数组索引
- includes()
- 表示某哥数组是否包含给定的值
- flat()
- 数组的扁平化
//1. from()
let arr2 = Array.from({
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
}); // ['a', 'b', 'c']
// 2. of()
Array.of(3, 11, 8) // [3,11,8]
Array(3) // [, , ,] length = 3
//3. fill() 接受三个参数
new Array(3).fill(7) // [7, 7, 7]
['a', 'b', 'c'].fill(7) // [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7, 'c']
//4. find()、findIndex() 接受三个参数,依次为当前的值、当前的位置和原数组
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10 ---> 如果是findIndex 返回 2
//5. includes()
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
//6. flat()
[1, 2, [3, [4, 5]]].flat() // [1,2,3,[4,5]]
[1, 2, [3, [4, 5]]].flat(2) // [1,2,3,4,5]
4. 对象新增了哪些方法?
- is()
- 比较两个值是否完全相等,相等
===
- 比较两个值是否完全相等,相等
- assign()
- 方法用于对象的合并,将源对象可枚举属性 复制到目标对象
- keys()
- 返回一个数组,成员是对象自身可遍历属性的键名
- values()
- 返回一个数组,成员是对象自身可遍历属性的键值
- entries()
- 返回一个二维数组,成员是对象自身可遍历属性的键值对数组
- fromEntries()
- 和
entries相反,返回一个对象
- 和
// 1. is()
Object.is('foo', 'foo'); //true
Object.is({}, {}); // false
// 2. assing()
Object.assign({a:1},{b:2},{c:3}) //{a:1, b:2, c:3}
// 3. keys()
Object.keys({foo: 'bar', baz: 42}) //['foo', 'baz']
// 4. values()
Object.values({foo: 'bar', baz: 42}) //['bar', 42]
// 5. entries()
Object.entries({foo: 'bar', baz: 42}) //[['foo', 'bar'], ['baz', 42]]
// 6. fromEntries()
Object.fromEntries([['foo', 'bar'], ['baz', 42]]) //{foo: 'bar', baz: 42}
5. 箭头函数和普通函数的区别?
- 写法不一样,剪头函数更加简洁
- 箭头函数没有自己的
this对象,它的this是它执行上下文的this - 剪头函数不能使用call、apply、bind改变
this - 不可以当作
构造函数,不能使用new - 没有argument
- 没有 prototype 属性
- 不可以使用
yield命令,因此箭头函数不能用作Generator函数
6. Set、Map是干什么用的?有什么区别?
-
Set
- 统称为集合,类似于数组,没有重复的元素
- 可以用来达到数组的去重效果
- 方法:
- add()
- delete()
- has()
- clear()
-
Map
- 是键值对的集合
- 数据过大时查找速度更快
- 方法:
- size
- set()
- get()
- has()
- delete()
- clear()
-
区别:
- Map 是键值对的集合,Set不是(可以认为只有键名或键值的集合)
- Set可以做数组去重,Map不可以
- 都可以通过for...of遍历
/** Set */
let a = new Set([1,2,2]) //[1,2]
let b = new Set([2,3,4])
// 并集
new Set([...a, ...b]) // Set {1,2,3,4}
// 交集
new Set([...a].fillter(x => b.has(x))) // set {2,3}
/** Map */
const myMap = new Map();
const keyStr = "{}"
myMap.set(keyStr, "我是值")
myMap.get(keyStr) // 我是值
const map = new Map([
['F', 'no'],
['T', 'yes'],
]);
// "F" no -- next --> "T" yes
map.forEach(function(value, key, map) {
console.log( key, value);
});
/** 区别 */
// red -- next --> green
for (let item of ['red', 'green']) {
console.log(item);
}
// F, no -- next --> T, yes
for(let [key, value] of map){
console.log(key, value)
}
7. proxy 是什么?有什么作用?它和reflect有什么区别?
proxy俗称代理,用于修改某些操作的默认行为,属于元编程。
proxy在目标对象的外层搭建了一层拦截,可以通过这层拦截,来对目标对象的操作进行拦截和监视
- 常见的方法:
- set
- 捕获器用于拦截对代理对象属性的设置操作
- get
- 捕获器用于拦截代理对象属性的读取操作
- apply
- 捕获器用于拦截函数的调用操作
- has
- 拦截
in操作符
- 拦截
- deleteProperty
- 拦截
delete操作符
- 拦截
- construct
- 拦截
new操作符
- 拦截
- set
let obj = {
name: "zhangsan",
age: 30
};
let handler = {
get: function(target, prop, receiver) {
console.log(`get key "${prop}"`);
return target[prop];
},
set: function(target, prop, value, receiver) {
console.log(`Setting property "${prop}" to ${value}`);
target[prop] = value;
}
};
let proxy = new Proxy(obj, handler);
console.log(proxy.name); // get key "name" zhangsan
proxy.age = 40; // Output: Setting property "age" to 40
/** apply */
let target = function(a, b){
return a + b;
}
let handler = {
apply: function(target, ctx, args){
return target(...args)
}
}
let p = new Proxy(target, handler);
p(1, 2) //3
8. 谈一谈 promise 和 async await 是什么?干什么用?他们的区别是什么?
promise 是一种异步编程
-
解决问题:
- 用来解决回掉地狱
- 方便后续方便维护
-
特点:
- 对象的状态不受外界影响
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果
- 链式操作降低了编码难度
- 代码可读性增强
-
缺点:
- 一旦新建就会立即执行,无法取消 promise
- 当处于pending状态时,无法得知目前进行到哪一个阶段
-
状态:
- pending 进行中
- fulfilled 已完成
- rejected 已失败
-
实例方法:
- then() 成功回掉
- catch() 失败回掉
- finally() 不管状态指向的是哪一种,都会执行操作
async...await
-
是什么?
- 也是一种异步编程,可以说是promise的语法糖或简写形式
- async 定义的函数返回一个 promise
-
注意:
- async 和 await是配对使用的,单独使用 await 会报错
-
区别:
- async await 可以用try catch同时处理同步和异步错误
- async await 更加简洁
9. 谈一谈promise.all()和.race()解决了什么问题?
all会将传入的数组中的所有promise全部运行完之后
- 全部成功,那么执行成功的回调函数,并将以数组的形式传入到回调中
- 有一个为失败,那么就会调用失败的回调
race可以理解为谁跑的最快,就执行谁的回调
- 可以用来实现请求超时
- 可以用来取消异步操作
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
const p2 = new Promise((resolve, reject) => {
reject('hello');
})
//进的是 catch
Promise.all([p1, p2])
.then(res => console.log(res))
.catch(e => console.log(e))
// 5秒之后 没有响应数据 则抛出错误
const p = Promise.race([
fetch('/api/xxx'),
new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error('request timeout')), 500)
})
])
p
.then(console.log)
.catch(console.log)
// 取消异步请求
const request = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("我是成功的");
}, 3000);
});
const cancel = new Promise((resolve, reject) => {
let btn = document.getElementById("btn");
btn.onclick = () => {
resolve("取消请求");
};
});
Promise.race([request, cancel])
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
10. genertor函数用过吗?可以解决什么问题?
genertor 生成器是es6提供的一种异步编程解决方案,是iterator的子类
-
特点:
- 解决了
以往函数,一旦运行无法中断的行为
- 解决了
-
用法:
- function关键字与函数之间需添加一个 *
- 函数体内使用
yield来返回表达式,可以有多个yield - 依次调用
next方法,获取对应yield表达式返回的数据
-
注意:
- 箭头函数不能使用 genertor
- yeild 表达式只能用在 genertor 函数里