闭包是你的朋友!
只需将以下小函数添加到您的顶级命名空间,您就可以开始 OOP,完成
- 封装,具有静态和实例、私有和公共变量和方法
- 遗产
- 类级注入(例如,用于单例服务)
- 没有限制,没有框架,只是简单的旧 Javascript
function clazz(_class, _super) {
var _prototype = Object.create((_super || function() {}).prototype);
var _deps = Array.isArray(_class) ? _class : [_class]; _class = _deps.pop();
_deps.push(_super);
_prototype.constructor = _class.apply(_prototype, _deps) || _prototype.constructor;
_prototype.constructor.prototype = _prototype;
return _prototype.constructor;
}
上面的函数简单地将给定类的原型和最终的父构造函数连接起来,并返回生成的构造函数,为实例化做好准备。
现在,您可以最自然地在几行代码中声明您的基类(即扩展 {}),包括静态、实例、公共和私有属性和方法:
MyBaseClass = clazz(function(_super) { // class closure, 'this' is the prototype
// local variables and functions declared here are private static variables and methods
// properties of 'this' declared here are public static variables and methods
return function MyBaseClass(arg1, ...) { // or: this.constructor = function(arg1, ...) {
// local variables and functions declared here are private instance variables and methods
// properties of 'this' declared here are public instance variables and methods
};
});
延长课程?也更自然:
MySubClass = clazz(function(_super) { // class closure, 'this' is the prototype
// local variables and functions are private static variables and methods
// properties of this are public static variables and methods
return function MySubClass(arg1, ...) // or: this.constructor = function(arg1, ...) {
// local variables and functions are private instance variables and methods
_super.apply(this, arguments); // or _super.call(this, arg1, ...)
// properties of 'this' are public instance variables and methods
};
}, MyBaseClass); // extend MyBaseClass
换句话说,将父类的构造函数传递给 clazz 函数,并添加_super.call(this, arg1, ...)
到子类的构造函数中,该构造函数使用所需的参数调用父类的构造函数。与任何标准继承方案一样,父构造函数调用必须首先出现在子构造函数中。
请注意,您可以自由地使用 显式命名构造函数this.constructor = function(arg1, ...) {...}
,或者this.constructor = function MyBaseClass(arg1, ...) {...}
如果您需要从构造函数内部的代码简单访问构造函数,或者甚至return function MyBaseClass(arg1, ...) {...}
像上面的代码一样简单地返回构造函数。哪个你觉得最舒服。
只需像通常从构造函数中一样从此类类中实例化对象:myObj = new MyBaseClass();
请注意闭包如何很好地封装类的所有功能,包括其原型和构造函数,为静态和实例、私有和公共属性和方法提供自然命名空间。类闭包中的代码完全没有约束。没有框架,没有约束,只是简单的旧 Javascript。闭包规则!
哦,如果您想将单例依赖项(例如服务)注入到您的类(即原型)中,clazz
请使用 AngularJS 为您执行此操作:
DependentClass = clazz([aService, function(_service, _super) { // class closure, 'this' is the prototype
// the injected _service dependency is available anywhere in this class
return function MySubClass(arg1, ...) // or: this.constructor = function(arg1, ...) {
_super.apply(this, arguments); // or _super.call(this, arg1, ...)
// the injected _service dependency is also available in the constructor
};
}], MyBaseClass); // extend MyBaseClass
正如上面的代码试图说明的那样,要将单例注入到一个类中,只需将类闭包作为最后一个条目放入包含所有依赖项的数组中。还要将对应的参数添加到参数前面的类闭包中,_super
并且与数组中的顺序相同。clazz
将数组中的依赖项作为参数注入到类闭包中。然后依赖关系在类闭包中的任何地方都可用,包括构造函数。
事实上,由于依赖项被注入到原型中,它们甚至在从类实例化任何对象之前就可用于静态方法。这对于连接您的应用程序或单元和端到端测试非常强大。它还消除了将单例注入构造函数的需要,否则会不必要地破坏构造函数的代码。
检查这个小提琴:http: //jsfiddle.net/5uzmyvdq/1/
欢迎反馈和建议!