Javascript OOP best practices?
我讨厌看到用JavaScript进行面向对象编程的许多不同方法。有人能告诉我,考虑到我想在一个大型项目上工作,我想让我的代码成为未来的证据,我应该使用哪种技术吗?
这些只是我提出的一些快速指导原则,如果其他人有任何有意义的内容需要添加,我将这个答案设置为社区wiki,这样您就可以轻松地进行编辑。
1 2 3 4 | window['Andrew']['JS'] = { addEvent: function(el,evName) {/*Stuff*/}, Rectangle: function(width,height) {/*Stuff*/} }; |
因此,您可以使用以下方法创建一个矩形对象:
1 | var myRect = new Andrew.JS.Rectangle(14,11); |
然后,您的代码将永远不会干扰或被其他任何人的
- 对象名称应大写,其他所有内容(变量、函数)应以小写字符开头,即
1
2var myRect = new Andrew.JS.Rectangle(14,11);
document.write(myRect.getArea()); - 确保每件事都有意义,即方法的动词,参数的名词+形容词。
1 | myRect.getAreaObject().inSquareFeet(); |
确保insquarefeet是由
1 2 3 4 5 6 7 8 9 10 11 12 13 | var Person = function() { this.name =""; this.sayHello = function () { alert(this.name +" says 'Hello!'"); return this; } } var bob = new Person(); bob.name ="Bob Poulton"; bob.sayHello(); |
尝试:
1 2 3 4 5 6 7 8 9 10 11 12 | var Person = function(name) { this.name = name; this.sayHello = function () { alert(this.name +" says 'Hello!'"); return this; } } var bob = new Person("Bob Poulton"); bob.sayHello(); |
我总是使用John Resig的:
http://ejohn.org/blog/simple-javascript-inheritance/
它很简单,不需要任何框架来运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | //Create and define Global NameSpace Object ( function(GlobalObject, $, undefined) { GlobalObject.Method = function() { ///<summary></summary> } GlobalObject.Functionality = {}; }) (GlobalObject = GlobalObject || {}, jQuery); //New object for specific functionality ( function(Events, $, undefined) { //Member Variables var Variable; // (Used for) , (type) // Initialize Events.Init = function() { ///<summary></summary> } // public method Events.PublicMethod = function(oParam) { ///<summary></summary> ///<param type=""></param> } // protected method (typically define in global object, but can be made available from here) GlobalObject.Functionality.ProtectedMethod = function() { ///<summary></summary> } // internal method (typically define in global object, but can be made available from here) GlobalObject.InternalMethod = function() { ///<summary></summary> } // private method var privateMethod = function() { ///<summary></summary> } }) (GlobalObject.Funcitonality.Events = GlobalObject.Funcitonality.Events || {}, jQuery ) // Reusable"class" object var oMultiInstanceClass = function() { // Memeber Variables again var oMember = null; // // Public method this.Init = function(oParam) { oMember = oParam; for ( n = 1; i < oMemeber.length; i += 1 ) { new this.SubClass.Init(oMember[i]); // you get the point, yeah? } } this.Subclass = function() { this.Init = function() { } } } |
其优点是它自动初始化全局对象,允许您维护代码的完整性,并根据定义将每一项功能组织成特定的分组。
这个结构是可靠的,它提供了所有基本的语法方面的东西,您可以在没有关键字的情况下从OOP中得到这些东西。
甚至还有一些巧妙的方法来设置接口。如果你选择这么做,一个简单的搜索会给你一些好的教程和提示。
甚至可以使用JavaScript和Visual Studio设置IntelliSense,然后定义每一个部分并引用它们,这样就可以使编写JavaScript更清晰、更易于管理。
根据您的情况使用这三种方法有助于保持全局名称空间的整洁,保持代码的有序性,并保持每个对象的关注点分离。如果使用正确。记住,如果不利用对象背后的逻辑,那么面向对象的设计是没有用的!
仅供参考,我认为Yui提供了一些关于这个主题的很好的教程
我对OOP的理想对象就像使用一个带有原型的实例方法:
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | var Users = function() { var _instance; this.prototype.getUsername = function(){/*...*/} this.prototype.getFirstname = function(){/*...*/} this.prototype.getSecurityHash = function(){/*...*/} /*...*/ /*Static Methods as such*/ return { /*Return a small Object*/ GetInstance : function() { if(_instance == null) { _instnance = new Users(arguments); } return _instnance; //Return the object }, New: function() { _instnance = null; //unset It return this.GetInstnace(arguments); } } } |
然后我总是使用如下:
1 2 3 4 5 6 | Firstname = Users.GetInstance('Robert','Pitt').getFirstname(); Username = Users.GetInstance().getUsername(); //Returns the above object. Me = Users.New('Robert',null); //Deletes the above object and creates a new instance. Father = Users.New('Peter','Piper'); //New Object Me.AddFather(Father); //Me Object. |
这就是我在构建一个JavascriptOO风格架构时所走的路。
因为您正在进行一个大型项目,我建议您使用一个类似mooolts的javascript框架http://mooolts.net/。
它具有良好的类和继承结构。
1 2 3 4 5 6 7 8 9 10 11 12 | function foo() { var bar = function() { console.log("i'm a private method"); return 1; }; var iAmAPrivateVariable = 1; return { publicMethod: function() { alert(iAmAPrivateVariable); }, publicVariable: bar() } } //usage var thing = foo() |
这是一种功能性的方法,它比您将看到的任何其他方法(如封装)都更适合它。
一般来说,你不应该在JavaScript中使用OO,因为很多原因,它不是一种很好的语言。想想这个带有歪斜括号和分号的方案,你将开始像专业人士那样编写语言。也就是说,有时候OO更适合。在这些情况下,上述通常是最佳选择
把遗产混为一谈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | function parent() { return { parentVariable: 2 }; } function foo() { var bar = function() { console.log("i'm a private method"); return 1; }; var iAmAPrivateVariable = 1; me = parent(); me.publicMethod = function() { alert(iAmAPrivateVariable); }; me.publicVariable = bar(); return me; } |
这使得事情稍微复杂一点,但实现了预期的最终结果,同时仍然采用面向对象概念的功能性方法(在本例中,使用decorator函数而不是真正的继承)。我喜欢整个方法的一点是,我们仍然以这种语言来处理对象——一个可以随意附加东西的属性包。
另一个需要注意的是,这与你将要从事的大多数工作中的大部分时间都会看到的截然不同,而且通常很难解释a)发生了什么,b)为什么对同事来说这是个好主意。
我使用这种模式,并建议您也使用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | function Person(firstname, lastname, age) { var self = this; var _ = {}; // Private members. var firstname = firstname; var lastname = lastname; var age = age || 'unknown'; // Private methods. function first_letter_to_uppercase(str) { return str.charAt(0).toUpperCase() + str.substr(1); } // Public members and methods. _.get_age = function() { return age; } _.get_name = function() { return first_letter_to_uppercase(firstname) + ' ' + first_letter_to_uppercase(lastname); } return _; } var p = new Person('vasya', 'pupkin', 23); alert("It's" + p.get_name() + ', he is ' + p.get_age() + ' years old.') |
您可以尝试使用一个简单、有用和快速的对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | var foo = { foo1: null, foo2: true, foo3: 24, foo4: new Array(), nameOfFunction1: function(){ alert("foo1"); }, nameOfFunction2: function(){ alert("foo2"); }, } |
要使用这个,必须创建这个对象的实例,并像Java中的对象一样使用:
1 | foo.nameOfFunction2(); |
您还可以查看其他解决方案的链接:http://www.javascriptkit.com/javautors/oopjs.shtml
我希望能回答你的问题。