重温es6中的注意点(部分)

闲来无事,点开 es6 的文档看看,复习复习一些需要注意的地方,小做总结。

  1. 暂时性死区
// 1. let/const
var tmp = 123;
if (true) {
    tmp = 'abc'; // ReferenceError
    let tmp;
}
// 2. 比较隐秘的死区
function bar(x = y, y = 2) {
    // error
    return [x, y];
}
  1. 函数结构默认参数
// 写法一, 对x和y分别设置默认值
function f1({ x = 0, y = 0 } = {}) {
    return [x, y];
}

// 写法二, 对{x,y} 设置默认值
function f2({ x, y } = { x: 0, y: 0 }) {
    return [x, y];
}

f1({}); // [0,0]
f2({}); // [undefined,undefined]
  1. 尾调用优化
/* -------------------------- 尾调用 -------------------------- */
// 形如:
function f(x) {
    return g(x);
}

// 以下情况都不是
function f(x) {
    let y = g(x);
    return y;
}
function f(x) {
    return g(x) + 1;
}
function f(x) {
    g(x);
}

/* -------------------------- 优化 -------------------------- */
// 函数在内存中会有调用栈,当尾调用不再使用外层函数的变量时,就可以释放外层函数的调用帧,从而达到内存优化
function f() {
    let m = 1;
    let n = 2;
    return g(m + n);
}
f();
/* -------------------------- 注意 -------------------------- */
function addOne(a) {
    var one = 1;
    function inner(b) {
        return b + one; // 使用到了外层函数的one, 所以addOne的调用帧不会被删除
    }
    return inner(a);
}
  1. 尾递归
// 尾递归是基于尾调用的, 因为递归很容易造成栈溢出, 但是尾递归始终只有一个调用帧, 绝对安全可靠
// 差 O(n)
function factorial(n) {
    if (n === 1) return 1;
    return n * factorial(n - 1);
}
factorial(5); // 120
// 优 O(1)
function factorial(n, total = 1) {
    if (n === 1) return total;
    return factorial(n - 1, n * total);
}

不难看出,从非递归转为递归主要就是把使用到的内部变量转移为函数的参数
ES6 的尾调用优化只在严格模式下开启, 因为正常模式下 arguments 和 caller 会跟踪调用栈, 尾调用优化调用栈被改写, 这两个变量失真;
严格模式会禁用这两个变量

  1. set & map
/* -------------------------- set -------------------------- */
// 特点就是不重复, 可以用来去重,取交集,并集,差集方便
let a = [1, 2, 2, 3],
    b = [3, 4, 5],
    c = [1, 4, 6];
[...new Set(a)]; // [1,2,3]
// 并
const res1 = [...new Set([...a, ...b])]; // [1,2,3,4,5]
let a1 = new Set(a),
    b1 = new Set(b);
// 交
const res2 = [...new Set([...a1].filter(item => b1.has(item)))]; // [3]
// 差
const res1 = [...new Set([...a1].filter(item => !b1.has(item)))]; // [1,2]

/* -------------------------- map -------------------------- */
// 特点就是v=>v的映射关系, key不再拘泥于字符串, 可以是对象,函数等; Map 既能保存键值对,又能够记住键的原始插⼊顺序
let map = new Map([[null, 1], [Symbol('正确'), 'true'], [function a{}, 'log']])
// Map { null => 1, Symbol(正确) => 'true', [Function: a] => 'log' }

/* -------------------------- WeakSet&WeakMap -------------------------- */
// 相对于Set和Map都没有size和clear()方法了
// WeakSet的值必须是对象, WeakMap的键必须是对象
// 都是弱引用, 不计入垃圾回收机制, 会自动回收, 可以避免内存泄露

// 主要说一下WeakMap可以设置私有变量
let _counter = new WeakMap();
let _action = new WeakMap();

class Countdown {
  constructor(counter, action) {
    _counter.set(this, counter);
    _action.set(this, action);
  }
  dec() {
    let counter = _counter.get(this);
    if (counter < 1) return;
    counter--;
    _counter.set(this, counter);
    if (counter === 0) {
      _action.get(this)();
    }
  }
}

let c = new Countdown(2, () => console.log('DONE'));

c.dec()
c.dec()
// DONE
  1. Proxy

顾名思义,代理,这里主要讲下 vue3 和 vue2 中的 Object.defineProperty 的区别。

proxy:

  • 代理的是整个对象, 可以监听所有属性的变化, 包括新增和删除
  • 有 13 中拦截

Object.defineProperty:

  • 劫持对象的属性, 只能监听属性的改变, 无法监测属性的新增和删除以及数组的新增和删除
  • 只有 get 和 set, get 收集依赖, set 触发更新
  1. class

ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this

在 react 中 super(props) 中的 props 也是必须的,但其实,即使不传 props,render 或其他方法也能访问到 this.props,因为 react 内部做了处理,必须传的原因是在 constructor 执行完毕前,拿不到 this.props

// React 内部
const instance = new YourComponent(props);
instance.props = props;

Why Do We Write super(props)?

Class 作为构造函数的语法糖,同时有 prototype 属性和__proto__属性,因此同时存在两条继承链。

class A {}
class B extends A {}

// 构造函数的原型链指向父函数的原型对象
B.prototype.__proto__ === A.prototype;
// 构造函数继承自父函数
B.__proto__ === A;

说起 class 不得不谈谈 React 中的 function 组件和 class 组件,react 在内部使用isReactComponent字段来检测是不是 class 组件,因为 class 都会继承 Component

class Component {}
Component.prototype.isReactComponent = {};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yokiizx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值