ES6知识点捡漏

128 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情 

proxy 代理 Reflect

const proxy = new Proxy({}, {})

应用,实现数组索引负数则取 length + index 的索引

const negativeArray = (els) => new Proxy(els, {
  get: (target, propKey, receiver) => Reflect.get(target,
    (+propKey < 0) ? String(target.length + +propKey) : propKey, receiver)
});


const unicorn = negativeArray([1,2,3]);

unicorn[-1] // '3'

生成各种 dom 节点的函数 dom

const dom = new Proxy({}, {
  get(target, property) {
    return function(attrs = {}, ...children) {
      const el = document.createElement(property);
      for (let prop of Object.keys(attrs)) {
        el.setAttribute(prop, attrs[prop]);
      }
      for (let child of children) {
        if (typeof child === 'string') {
          child = document.createTextNode(child);
        }
        el.appendChild(child);
      }
      return el;
    }
  }
});
const el = dom.div({},
  'Hello, my name is ',
  dom.a({href: '//example.com'}, 'Mark'),
  '. I like:',
  dom.ul({},
    dom.li({}, 'The web'),
    dom.li({}, 'Food'),
    dom.li({}, '…actually that's it')
  )
);
document.body.appendChild(el);

img3.png 配置接口请求参考地址 ReflectReflect Reflect

Reflect

1.Reflect和Proxy对象方法一一对应。都能找到 2.让 Object的操作都变成函数行为 如 比如name in obj和delete obj[name]对应Reflect.has(obj, name)和Reflect.deleteProperty(obj, name) 3.Object.defineProperty报错,Reflect.defineProperty(target, property, attributes)会直接返回 false 4.为了将语言内部方法和 Object 方法区分开,后面语言内部方法全部从 Reflect 上获取

Iterator 与 generator

for...in 遍历对象不适合遍历数组,遍历的是键名 for...of 实现了 Iterator 接口就可遍历。通用的,遍历值,普通对象不能直接使用,要Object.keys处理 forEach 不能跳出循环。

for of 可以自动遍历

function* bar() {
    yield 'a';
    yield 'b';
}

function* foo() {
  yield 1;
  yield 2;
    for (let i of bar()) {
        console.log(i);
    }
    // 或者用yield* bar()   yield*表达式,用来在一个 Generator 函数里面执行另一个 Generator 函数
  yield 3;
  yield 4;
  yield 5;
  return 6;
}
for (let v of foo()) {
  console.log(v);
}
// 12ab345
  1. 状态切换。更简洁,更安全,避免篡改。
var clock = function* () {
  while (true) {
    console.log('collect!');
    yield;
    console.log('unCollect!');
    yield;
  }
}();
clock()
clock()
clock()
clock()

async await

是 generator 的语法糖。内置执行器,返回的是 promise 对象 原理

// awaiting.js
let output;
async function main() {
  const dynamic = await import(someMission);
  const data = await fetch(url);
  output = someProcess(dynamic.default, data);
}
main();
export { output };

---------------------


// awaiting.js
let output;
(async function1 main() {
    const dynamic = await import(someMission);
    const data = await fetch(url);
    output = someProcess(dynamic.default, data);
})();
export { output };

规范

  1. 一律使用单引号,反引号
  2. 优先使用解构赋值。
const [first, second] = arr;
// bad

function getFullName(user) {
    const firstName = user.firstName;
    const lastName = user.lastName;
}
// good
function getFullName(obj) {
  const { firstName, lastName } = obj;
}
// best
function getFullName({ firstName, lastName }) {
}
  1. 对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性不可避免,要使用Object.assign方法。尽量采用简洁表达。
// bad
const a = {};
a.x = 3;
// if reshape unavoidable
const a = {};
Object.assign(a, { x: 3 });
// good
const a = { x: null };
a.x = 3;


// =====================================

// bad
const obj = {
    id: 5,
    name: 'San Francisco',
};
obj[getKey('enabled')] = true;
// good
const obj = {
    id: 5,
    name: 'San Francisco',
    [getKey('enabled')]: true,
};


// =============================================
// bad
const atom = {
    ref: ref,
    value: 1,
    addValue: function (value) {
        return atom.value + value;
    },
};
// good
const atom = {
    ref,
    value: 1,
    addValue(value) {
        return atom.value + value;
    },
};


//==================使用默认值语法设置函数参数的默认值。===============
// bad
function handleThings(opts) {
    opts = opts || {};
}
// good
function handleThings(opts = {}) {
    // ...
}


// ================ 使用 rest 不在函数中使用arguments数组 ===================
function funName(a, b, ...others) {
    
}
funName("1", "2", "3", "4");


  1. 使用import取代require, 使用export取代module.exports。

装饰器

类装饰器

本质是装饰器本质就是编译时执行的高阶函数。函数参数就是装饰器参数@decorator(params) 返回的函数参数target就是装饰的类本身

function decorator(params) {
  return function(target) {
    target.addParams = params;
  }
}

@decorator(params)
class MyClass{}


function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}

@testable(true)
class MyTestable {}
MyTestableClass.isTestable // true


@testable(false)
class MyNotTestable {}
MyClass.isTestable // false

@testable 就是一个装饰器,装饰器修改了类的行为,为类添加了isTestable属性,testable函数对应的target参数就是类本身。

class MyComponent extends React.Component {}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);

// 可以改写为
@connect(mapStateToProps, mapDispatchToProps)
export default class MyComponent extends React.Component {}

// 相当于执行了
function connect(mapStateToProps, mapDispatchToProps) {
    return function(target) {
        // ...
    }
}

方法装饰器

仅限修饰类下面定义的方法,不可修饰单独函数。

class AddClass {
  @log
  add(a, b) {
    return a + b;
  }
}

/**
 * 
 * @param target  __proto__ 原型对象,因为没有继承关系target就相当于AddClass.prototype === instance.__proto__
 * @param name   修饰的方法名
 * @param descriptor  方法的描述,实际就是方法本身
 * @returns {*}
 */
function log(target, name, descriptor) {
  var oldValue = descriptor.value;
  // 相当于给add方法重新赋值为自定义的方法,再执行前加上日志
  descriptor.value = function() {
    console.log(`${name}的参数是`, arguments);
    return oldValue.apply(this, arguments);
  };
  return descriptor;
}
const addClass = new AddClass();
console.log(addClass.add(2, 4))



相关链接

ES6相关