行为委托

什么是行为委托?
简单来说就是一种设计模式,不同于传统的构造函数的“类”式设计。


在这之前先说一下原型的基本知识。
什么是原型?简单来说就是一个对象内部关联另外一个对象,本质来说就是对象与对象之间的关联;
一个对象本身没有属性或者方法会到原型对象上查找。

这里每个例子会通过构造函数,class和行为委托来不同实现,不过不会评论class,是否使用class取决于你的观点。


先看一个例子,构造函数写法

function Foo(name) {
    this.name = name;
}
Foo.prototype.age = function() {
    console.log(this.name);
};
function Fn(name) {
    Foo.call(this);
    this.name = name;
}
Fn.prototype = Object.create(Foo.prototype);
Fn.prototype.constructor = Fn.prototype;
Fn.prototype.set = function(value) {
    this.name = value;
};
var a1 = new Fn('zhangsan');
a1.age(); //zhangsan
var a2 = new Fn('lisi');
a2.set('xiaowu'); 
a2.age(); //xiaowu

class写法

class Foo {
    constructor(name) {
    this.name = name;
    }
    age() {
        console.log(this.name);
    }
}
class Fn extends Foo {
    constructor(name) {
        super();
        this.name = name;
    }
    set(value) {
        this.name = value;
    }
}
var a1 = new Fn('zhangsan');
a1.age(); //zhangsan
var a2 = new Fn('lisi');
a2.set('xiaowu'); 
a2.age(); //xiaowu            

行为委托写法

var Foo = {
        const(name) {
            this.name = name;
    },
    age() {
        console.log(this.name);
    }
};
var Fn = Object.create(Foo);
Fn.set = function (value) {
    this.name = value;
};
var a1 = Object.create(Fn);
a1.const('zhangsan');
a1.age(); //zhangsan
var a2 = Object.create(Fn);
a2.set('xiaowu'); 
a2.age(); //xiaowu    


可以看到比起构造函数,行为委托是通过原型链来实现的,他值关心一件事情,对象指向的关系。

再来看一个复杂一些的例子,为dom添加样式。

function Foo(value) {
    this.dom = value;
}
Foo.prototype.div = function () {
    var div = document.createElement(this.dom);
    this._dom = document.body.appendChild(div);
    return this._dom;
};
Foo.prototype.get = function () {
    return this._dom;
};
function Fn(text, cssText) {
    Foo.call(this, 'div');
    this.text = text;
    this.cssText = cssText;
}
Fn.prototype = Object.create(Foo.prototype);
Fn.prototype.constructor = Fn.prototype;
    Fn.prototype.set = function () {
    this.div();
    var div = this.get();
    div.textContent = this.text;
    Object.keys(this.cssText).forEach((name) => {
        div.style.cssText += `${name}: ${this.cssText[name]}`;
    });
};
var a = new Fn('hi', {color: 'red', "font-size": '16px'});
a.set();    

class写法

class Foo {
    constructor(value) {
        this.dom = value;
    }
    div() {
        var div = document.createElement(this.dom);
        this._dom = document.body.appendChild(div);
    return this._dom;
    }
    get() {
        return this._dom;
    }
}
class Fn extends Foo {
    constructor(text, cssText) {
    super('div');
    this.text = text;
    this.cssText = cssText;
}
set() {
    super.div();
    var div = super.get();
    div.textContent = this.text;
    Object.keys(this.cssText).forEach((name) => {
        div.style.cssText += `${name}: ${this.cssText[name]}`;
    });
}
}
var a = new Fn('hi', { color: 'red', "font-size": '16px' });
a.set();            

  

行为委托写法

var Foo = {
        const(value) {
        this.dom = value;
},
    div() {
        var div = document.createElement(this.dom);
        this._dom = document.body.appendChild(div);
        return this._dom;
},
    get() {
        return this._dom;
    }
};
var Fn = Object.create(Foo);
Fn.constructor = function (text, cssText) {
    this.const.call(this, 'div');
    this.text = text;
    this.cssText = cssText;
};
Fn.set = function () {
    this.div();
    let div = this.get();
    div.textContent = this.text;
    Object.keys(this.cssText).forEach((name) => {
        div.style.cssText += `${name}: ${this.cssText[name]}`;
    });
};
var a = Object.create(Fn);
a.constructor('hi', { color: 'red', "font-size": '16px' });
a.set();        

注意点:
1.在使用行为委托时要避免标识符的重名,因为行为委托是基于原型链,不同于“类”的设计模式,可以构造函数与实例对象同时定义相同的名称的标识符。

2.两个委托对象无法互相委托,假设一个a对象关联b对象,然后b对象再关联a对象,如果两个引用了一个两个对象都不存在的属性或者方法,那么就会在原型链上形成无限循环。

猜你喜欢

转载自www.cnblogs.com/boses/p/9575247.html