ES6知识点

57 阅读6分钟

第一次写知识点,如有写不好的地方欢迎指出,也可以当作面试的知识点,我知道写的不好,以后会越写越好的。哈哈哈哈哈哈哈

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操作符
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 函数里