给“类”库添加方法
现在,我们的“类”库(class library)译注1 包含了生成一个实例并初始化这个实例的功能,给类添加属性和给构造函数添加属性是一样的。
直接给类设置属性和设置其静态成员是等价的:
- var Person = new Class;
- // 直接给类添加静态方法
- Person.find = function(id){ /* ... */ };
- // 这样我们可以直接调用它们
- var person = Person.find(1);
- 给类的原型设置的属性在类的实例中也是可用的:
- var Person = new Class;
- // 在原型中定义函数
- Person.prototype.save = function(){ /* ... */ };
- // 这样就可以在实例中调用它们
- var person = new Person;
- person.save();
广州网站建设,广州网站设计,广州网站制作,网站建设,网站设计,广州网站建设公司,广州网站设计公司
但在我看来这种语法有些绕,不切实际且不够简洁,很难一眼就分辨出类的静态属性和实例的属性。因此我们采用另外一种不同的方法来给类添加属性,这里用到了两个函数extend() 和include() :- var Class = function () {
- var klass = function () {
- this.init.apply(this, arguments);
- };
- klass.prototype.init = function () {};
- // 定义 prototype 的别名
- klassklass.fn = klass.prototype;
- // 定义类的别名
- klassklass.fn.parent = klass;
- // 给类添加属性
- klass.extend = function (obj) {
- var extended = obj.extended;
- for (var i in obj) {
- klass[i] = obj[i];
- }
- if (extended) extended(klass)
- };
- // 给实例添加属性
- klass.include = function (obj) {
- var included = obj.included;
- for (var i in obj) {
- klass.fn[i] = obj[i];
- }
- if (included) included(klass)
- };
- return klass;
- };
这段代码是“类”库的增强版,我们使用extend() 函数来生成一个类,这个函数的参数是一个对象。通过迭代将对象的属性直接复制到类上:
- var Person = new Class;
- Person.extend({
- find: function(id) { /* ... */ },
- exists: functions(id) { /* ... */ }
- });
- var person = Person.find(1);
include() 函数的工作原理也是一样的,只不过不是将属性复制至类中,而是复制至类的原型中。换句话说,这里的属性是类实例的属性,而不是类的静态属性。
- var Person = new Class;
- Person.include({
- save: function(id) { /* ... */ },
- destroy: functions(id) { /* ... */ }
- });
- var person = new Person;
- person.save();
同样地,这里的实现支持extended 和included 回调。将属性传入对象后就会触发这两个回调:
- Person.extend({
- extended: function(klass) {
- console.log(klass, " was extended!");
- }
- });
广州网站建设,广州网站设计,广州网站制作,网站建设,网站设计,广州网站建设公司,广州网站设计公司
如果你基于Ruby 实现过类,会感觉它的写法与此很相近。这种写法之美在于它已经可以支持模块了。模块是可重用的代码段,用这种方法可以实现各种继承,用来在类之间共享通用的属性。- var ORMModule = {
- save: function(){
- // 共享的函数
- }
- };
- var Person = new Class;
- var Asset = new Class;
- Person.include(ORMModule);
- Asset.include(ORMModule);