在JavaScript中使用OO似乎有很多不同的方法。
我喜欢:
function ClassA(){};
ClassA.prototype={
someFunc:function(a,b,c){},
otherFunc:function(){}
}
var c=new ClassA();
并且从未使用过超出此功能的功能(尽管是一个熟练的OOer)。我怀疑这是老式的,因为我经常看到新的闪烁变体,这让我想知道我是否选择了最好的方法。例如,你可以在构造函数方法中创建魔法来创建私有变量和访问器方法,我认为(直到最近)是不可能的。子类化怎么样?我不知道如何实现这一点,但它现在必须有某种共同模式。
你是怎么做到的?为什么?
答案 0 :(得分:6)
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中执行此操作的唯一方法)。
一般来说,你不应该在javascript中做OO,因为很多原因,它不是那么好的语言。认为方案有波浪括号和分号,你将开始像专业人士那样编写语言。话虽如此,有时OO更合适。在这些情况下,以上通常是最好的选择
编辑:将继承带入混合
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;
}
这使得事情变得更加复杂,但是在仍然采用OO概念的功能方法(在这种情况下,使用装饰器函数而不是真正的继承)的同时实现了期望的最终结果。我对整个方法的喜欢之处在于,我们仍然按照这种语言的方式处理对象 - 可以随意附加内容的属性包。
EDIT2:
只是想在信用到期时给予信任,这种方法对于doug crockford在Javascript:The Good Parts中的建议略有简化。如果你想把你的js技能提升到一个新的水平,我强烈建议从那里开始。我不认为我从这么小的书中学到了很多东西。
另一个注意事项是,这与你在大多数工作中大部分时间都会看到的情况截然不同,往往很难解释a)发生了什么,以及b)为什么会这样对同事来说是一个好主意。
答案 1 :(得分:5)
因为John Resig这么说。
答案 2 :(得分:2)
function Superclass() { }
Superclass.prototype.someFunc = function() { };
function Subclass() { }
Subclass.prototype = new Superclass();
Subclass.prototype.anotherFunc = function() { };
var obj = new Subclass();
这构建了obj -> Subclass.prototype -> Superclass.prototype -> Object.prototype
的“原型链”。
几乎每个用于JavaScript的OOP库都建立在这种技术之上,提供了抽象大部分原型“魔法”的函数。
答案 3 :(得分:1)
我认为joose是一种非常酷的方式在javascript中执行OOP http://code.google.com/p/joose-js/
答案 4 :(得分:1)
JavaScript中的对象与几乎所有其他高端语言都不同。它们不是基于类(如Java,C ++,PHP等),而是基于原型的。因此,必须对面向对象编程的基本范例进行相当大的修改。那些不能或不想重新思考并坚持使用基于类的思维的人必须在JavaScript中构建基于类的逻辑,或者使用已经构建它的其他人的代码。
答案 5 :(得分:0)
我喜欢做类似
的事情// namespace "My"
var My = new function {
// private methods
/**
* Create a unique empty function.
* @return {Function} function(){}
*/
function createFn () {return function(){}}
/** A reusable empty function. */
function emptyFn () {}
/**
* Clone an object
* @param {Object} obj Object to clone
* @return {Object} Cloned object
*/
function clone (obj) { emptyFn.prototype=obj; return new emptyFn() }
// public methods
/**
* Merge two objects
* @param {Object} dst Destination object
* @param {Object} src Source object
* @param {Object} [options] Optional settings
* @return {Object} Destination object
*/
this.merge = function (dst, src, options) {
if (!options) options={};
for (var p in src) if (src.hasOwnProperty(p)) {
var isDef=dst.hasOwnProperty(p);
if ((options.noPrivate && p.charAt(0)=='_') ||
(options.soft && isDef) ||
(options.update && !isDef)) continue;
dst[p]=src[p];
}
return dst;
}
/**
* Extend a constructor with a subtype
* @param {Function} superCtor Constructor of supertype
* @param {Function} subCtor Constructor of subtype
* @param {Object} [options] Optional settings
* @return {Function} Constructor of subtype
*/
this.extend = function (superCtor, subCtor, options) {
if (!subCtor) subCtor=createFn();
if (!options) options={};
if (!options.noStatic) this.merge(subCtor, superCtor, options);
var oldProto=subCtor.prototype;
subCtor.prototype=clone(superCtor.prototype);
this.merge(subCtor.prototype, oldProto);
if (!options.noCtor) subCtor.prototype.constructor=subCtor;
return subCtor;
}
}
然后就像......
// namespace "My.CoolApp"
My.CoolApp = new function(){
// My.CoolApp.ClassA
this.ClassA = new function(){
// ClassA private static
var count=0;
// ClassA constructor
function ClassA (arg1) {
count++;
this.someParam=arg1;
}
// ClassA public static
My.merge(ClassA, {
create: function (arg1) {
return new ClassA(arg1);
}
}
// ClassA public
My.merge(ClassA.prototype, {
doStuff : function (arg1) {
alert('Doing stuff with ' + arg1);
},
doOtherStuff : function (arg1) {
alert('Doing other stuff with ' + arg1);
}
}
return ClassA;
}
// My.CoolApp.ClassB
this.ClassB = new function(){
My.extend(My.CoolApp.ClassA, ClassB);
// ClassB constructor
function ClassB () {
ClassA.apply(this, arguments);
}
return ClassB;
}
}
... clone
函数是继承的关键。简而言之:
答案 6 :(得分:0)
用于画布的Javascript中的OOP
查看js中有用的OOP在不同情况下的效果......这样可以绘制正方形和圆形as objects
,以便您可以根据需要返回并循环或操纵它们。
function Shape(x,y,color){
this.x = x
this.y = y
this.color = color
}
function Square(height,width,color){
Shape.call(this, event.x, event.y, color)
this.height = height
this.width = width
this.x -= canvas.offsetLeft + (this.height/2)
this.y -= canvas.offsetTop + (this.width/2)
}
Square.prototype = new Shape();
Square.prototype.draw = function(color){
ctx.fillStyle = color
ctx.fillRect(this.x,this.y,this.height,this.width)
}
function Circle(color, width){
Shape.call(this)
this.x = event.x -60
this.y = event.y -60
this.width = width
}
Circle.prototype = new Shape();
Circle.prototype.draw = function(color){
ctx.beginPath()
ctx.arc(this.x,this.y,this.width,0,2*Math.PI, false);
ctx.fillStyle = color
ctx.fill()
}