【《你不知道的JS(中卷)》】六、行为委托

六、行为委托:

​ 总结第五章,JS中的[[Prototype]]机制就是 对象之间的关联关系

一)、面向委托的设计:

​ 想要学习更直观的使用[[Prototype]],必须认识到它代表了一种 不同于类的设计模式

1、类理论:

​ 类设计模式鼓励你在继承时使用方法重写(和多态),子类的许多行为可以先“抽象”到父类然后再用子类进行特殊化(重写)。

​ 例:

​ 父类Task,定义所有任务都有的行为。子类XYZ、ABC继承Task,并添加一些特殊的行为来处理对应的任务。

2、委托理论:

​ 相比面向类(面向对象,OOP),这种编码风格称为对象关联,(OLOO, objects linked to other objects)。

​ 例:

​ 定义一个Task对象,包含所有任务都可以使用的具体行为。接着对于每个任务(XYZ、ABC)都定义一个对象来存储对应的数据和行为。你会把特定的任务对象都关联到Task功能对象上,让它们在需要的时候进行委托。

  • 在[[Prototype]]委托中最好把状态保存在委托者(XYZ、ABC)而不是委托目标(Task)上。

  • 该设计模式要求尽量少使用容易被重写的通用方法名,提倡使用更有描述性的方法名,尤其是要写清相应对象行为的类型。

  • 在API接口的设计中,委托最好在内部实现,不要直接暴露出去。

委托行为意味着某些对象(XYZ)在找不到属性或者方法引用时会把这个请求委托给另一个对象(Task)。这是一种极其强大的设计模式,和父类、子类、继承、多态等概念完全不同。在你的脑海中 对象并不是按照父类到子类的关系垂直组织的,而是通过任意方向的委托关联并排组织的

1)、互相委托(禁止):

​ 你无法在两个或两个以上互相(双向)委托的对象之间创建循环委托。

2)、调试:

​ 对象关联风格的代码中,不需要关注谁“构造了”对象,浏览器调试中“构造函数名称”的跟踪没有意义。

3、比较思维模型:

(“原型”)面向对象风格:

function Foo(who) {
  this.me = who;
} 
Foo.prototype.identify = function () {
  return "I am " + this.me;
};

function Bar(who) {
  Foo.call(this, who);
}
Bar.prototype = Object.create(Foo.prototype);

Bar.prototype.speak = function () {
  alert("Hello," + this.identify() + ".");
};

var b1 = new Bar("b1");
var b2 = new Bar("b2");

b1.speak();
b2.speak();

对象关联风格:

Foo = {
  init: function (who) {
    this.me = who;
  },
  identify: function () {
    return "I am " + this.me;
  }
};

Bar = Object.create(Foo);
Bar.speak = function () {
  alert("Hello, " + this.identify() + ".");
};

var b1 = Object.create(Bar);
b1.init("b1");
var b2 = Object.create(Bar);
b2.init("b2");

b1.speak();
b2.speak();

​ 可以明显看出,下面的代码更加简洁。我们只是把对象关联起来,并不需要那些既复杂又令人困惑的模仿类的行为(构造函数、原型以及new)

二)、类与对象:

​ 以Web开发中非常典型的前端常见:创建UI控件为例。

1、控件“类”:

​ ES6中的语法糖“class”可以极大地改善丑陋地显式伪多态。

2、委托控件对象:

  • 使用类构造函数,需要在同一个步骤中实现构造和初始化。在许多情况下依照对象关联模式,把这两步分开更灵活。

三)、更简洁的设计:

四)、更好的语法:

​ ES6中引入class关键字,可以更简洁地定义类方法。同时在ES6中可以在任意对象的字面形式中使用 简洁方法声明。但是有一个缺点:自我引用(递归、事件(解除)绑定,等等)更难

五)、内省:

​ 内省就是检查实例的类型。类实例的自省主要目的是通过创建方式来判断对象的结构和功能。

JS中可以使用instanceof进行自省,也可以利用 鸭子类型

if (a1.something) {
    a1.something();
}
  • 当判断a1具有something()方法后,就可以调用该方法。
  • ES6的Promise就是典型的“鸭子类型”。

六)、小结:

​ 行为委托是一种设计模式,认为对象之间是兄弟关系,互相委托,而不是父类和子类的关系。

​ 对象关联是一种编码风格,它倡导的是直接创建和关联对象,不把它们抽象成类。

猜你喜欢

转载自www.cnblogs.com/enmac/p/13191410.html