所谓ES6的常用应用
- const/let
- 箭头函数
- Promise
- async await
- 解构/扩展运算符
- Object assgin
- class static
- 数组遍历api
- Reflect
Reflect.defineProperty(Vue.prototype, this.name, {
value: this,
writable: false,
enumerable: false,
configurable: false
});
包装模式
装饰模式和适配器模式都是 包装模式 (Wrapper Pattern),它们都是通过封装其他对象达到设计的目的的,但是它们的形态有很大区别。
- 适配器模式我们使用的场景比较多,比如连接不同数据库的情况,你需要包装现有的模块接口,从而使之适配数据库 —— 好比你手机使用转接口来适配插座那样;
装饰类
// 装饰类
@annotation
class MyClass { }
function annotation(target) {
target.annotated = true;
}
装饰方法或属性
https://github.com/mqyqingfeng/Blog/issues/109
装饰方法
装饰方法本质上还是使用 Object.defineProperty() 来实现的。
Decorators 的本质是利用了 ES5 的 Object.defineProperty 属性,这三个参数其实是和 Object.defineProperty 参数一致的
以上我们都是用于修饰类方法,我们获取值的方式为:
const method = descriptor.value;
方法装饰器有3个参数
- target
- key 方法名称
- desciptor 描述对象
@gang('The Warriors', 'Coney Island')
class Group1 {
constructor(){
}
}
@gang('The Riffs', 'Gramercy Park')
class Group2 {
constructor(){
}
}
@gang('Turnbull ACs', 'Gunhill')
class Group3 {
constructor(){
}
}
function gang(name, location) {
return function(target) {
target.locName = name;
target.location = location;
}
}
console.log('location=',Group1.location)
console.log('location=',Group2.location)
console.log('location=',Group3.location)
应用
装饰模式经典的应用是 AOP 编程,比如“日志系统”
log注释
class Math {
@log
add(a, b) {
return a + b;
}
}
function log(target, name, descriptor) {
var oldValue = descriptor.value;
descriptor.value = function(...args) {
console.log(`Calling ${name} with`, args);
return oldValue.apply(this, args);
};
return descriptor;
}
const math = new Math();
// Calling add with [2, 4]
math.add(2, 4);
mixin
const SingerMixin = {
sing(sound) {
alert(sound);
}
};
const FlyMixin = {
// All types of property descriptors are supported
get speed() {},
fly() {},
land() {}
};
@mixin(SingerMixin, FlyMixin)
class Bird {
singMatingCall() {
this.sing('tweet tweet');
}
}
var bird = new Bird();
bird.singMatingCall();
// alerts "tweet tweet"
function mixin(...mixins) {
return target => {
if (!mixins.length) {
throw new SyntaxError(`@mixin() class ${target.name} requires at least one mixin as an argument`);
}
for (let i = 0, l = mixins.length; i < l; i++) {
const descs = Object.getOwnPropertyDescriptors(mixins[i]);
const keys = Object.getOwnPropertyNames(descs);
for (let j = 0, k = keys.length; j < k; j++) {
const key = keys[j];
if (!target.prototype.hasOwnProperty(key)) {
Object.defineProperty(target.prototype, key, descs[key]);
}
}
}
};
}
debonce
function _debounce(func, wait, immediate) {
// return 一个function
// 缓存timeout定时器ID
var timeout = null;
// wrapper function
// 闭包 return的fn 就被称为闭包。
return function () {
// 缓存this
var context = this;
var args = arguments;
//连续触发fn 如果 假设一个用户一直触发这个函数,且每次触发函数的间隔小于wait,防抖的情况下只会调用一次
if (timeout) clearTimeout(timeout);
if (immediate) {
// 是否马上调用
// 第一次按下 立即调用
// 然后再wait之内连续按下,timeout有了,不会立即调用,会清除timeout定时器,直到wait之后,timeout = null
var callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
// 不难看出如果用户调用该函数的间隔小于wait的情况下,上一次的时间还未到就被清除了,并不会执行函数
// 大于wait 函数才会被执行
else {
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}
function debounce(wait, immediate) {
return function handleDescriptor(target, key, descriptor) {
const callback = descriptor.value;
if (typeof callback !== 'function') {
throw new SyntaxError('Only functions can be debounced');
}
var fn = _debounce(callback, wait, immediate)
// 这样写什么意思?
// return 一个descriptor
return {
...descriptor,
value() {
fn()
}
};
}
}
钢铁侠的例子
function decorateArmour(target, key, descriptor) {
// 装饰的是init方法,必须调用init
const method = descriptor.value;
let moreDef = 100;
let ret;
descriptor.value = (...args)=>{
args[0] += moreDef;
ret = method.apply(target, args);
return ret;
}
return descriptor;
}
class Man{
constructor(def = 2,atk = 3,hp = 3){
this.init(def,atk,hp);
}
@decorateArmour
init(def,atk,hp){
this.def = def; // 防御值
this.atk = atk; // 攻击力
this.hp = hp; // 血量
}
toString(){
return `防御力:${this.def},攻击力:${this.atk},血量:${this.hp}`;
}
}
var tony = new Man();
console.log(`当前状态 ===> ${tony}`);
// 输出:当前状态 ===> 防御力:102,攻击力:3,血量:3