JavaScript中“抽象”函数的最佳实践?

时间:2011-09-19 21:22:08

标签: javascript functional-programming abstract-class

我刚刚编写了一些JavaScript代码,以及我认为创建带闭包和某些函数的对象的良好实践:

var myStuff = (function() {
 var number = 0;
 var fn = {};
 fn.increment = function() { number++; };
 fn.decrement = function() { number--; };
 fn.getNumber = function() { return number; };
 return fn;
})();

myStuff.increment();
myStuff.increment();
alert(myStuff.getNumber()); // alerts '2'

编写像上一个代码片段一样的代码没有问题。我想编写一些功能类似于OOP“抽象”类的代码。以下是我努力的结果:

var myStuff = (function () {
var number = 0;
var fn = {};
fn.increment = function () { number++; };
fn.decrement = function () { number--; };
fn.doSomethingCrazy = function () { throw new Error('not implemented'); }; // I want to specify later what this does.
fn.doSomethingCrazyTwice = function () { fn.doSomethingCrazy(); fn.doSomethingCrazy(); };
fn.getNumber = function () { return number; };
return fn;
})();

myStuff.doSomethingCrazy = function () { this.increment(); this.increment(); };
myStuff.doSomethingCrazyTwice();
alert(myStuff.getNumber()); // alerts '4'

上面的代码片段有效,但看起来并不优雅。也许我正在尝试强制JavaScript(一种函数式语言)来做一些它不打算做的事情(对象继承)

在JavaScript中定义对象的好方法是什么,以便稍后可以定义该对象的功能?

5 个答案:

答案 0 :(得分:20)

只是不要定义功能。

Javascript是一种 duck-typed 语言。如果它看起来像一只鸭子,它像鸭子一样嘎嘎叫,它就是一只鸭子 你不需要做任何特别的事情来完成这项工作;只要在调用它时该函数存在,它就可以正常工作。

如果您在没有该功能的实例上调用它,您将在呼叫站点收到错误。

答案 1 :(得分:9)

我同意SLaks,没有必要定义这个功能,但无论如何我都倾向于。那是因为对我而言,重要的部分是在文档中。当有人读我的课时,我希望它清楚你必须实现这些方法,传递什么参数以及应该返回什么。

这是来自工作中的文件。有一个基本类的功能的多个实现,每隔一段时间进行数据加载。

/**
 * Called when data is received and should update the data buffer
 * for each of the charts 
 * 
 * @abstract
 * @param {cci.ads.Wave[]} waves
 * @void
 */
updateChartsData: function(waves){
    throw "Abstract method updateChartsData not implemented";
},

2019年更新

如果可以Declaring abstract method in TypeScript

,请使用TypeScript

答案 2 :(得分:7)

随着我们的团队不断发展,我们的javascript项目变得越来越复杂,我们也必须开始实现OO功能。

在我们的javascript'摘要'方法我们只是抛出错误,或弹出警报。这是一个来自Page对象的例子:

Page.initialLoad = function() { //abstract
    alert('Page.initialLoad not implemented');
};

在java世界中它与以下类似:

public void abstract initialLoad();

Java代码提供了编译时错误,但是在Javascript中我们会得到运行时错误。 (一个脏的错误对话框,说明实现对象还没有实现该方法)。

我们有许多使用Page对象的不同团队;鸭子打字的哲学'绝对不会与我们一起切割它。没有这些伪抽象的'方法我们普遍缺乏API通信,有时我们会破坏超级对象(即因为用户不知道他们应该实现该方法)。

我已经厌倦了这种“打字”的问题。哲学。我不确定支持者是否曾经参与过10多个开发人员的复杂Javascript项目。

答案 3 :(得分:3)

如果你没有找到优雅的方式,可能有一种方法可以创建一些函数来使流程变得更好。但回到主题......

是的,Javascript具有内置委托,即继承,通过原型

给出一个原型对象:

var proto = {
    f: function(){ console.log(this.x); }
}

我们可以创建一个从中继承的新对象:

var obj = Object.create(proto);
obj.x = 42;

obj.f(); //should work!

for(var i in obj) console.log(i);
//should print x, f and some other stuff perhaps

请注意,并不总是支持通过Object.create直接执行操作(旧浏览器等)。旧的(有些人可能会说,正常)方式做的事情是通过时髦的运算符(不要过多地考虑名称 - 它的目的是混淆分散Java人的注意力)

function Constructor(arg){
    this.x = arg;
}

Constructor.prototype = {
    f: function(){ ... }
};

var obj = new Constructor(17);
obj.f();

原型继承需要考虑的一个重要区别是缺少私有变量。 只能继承公共变量!因此,常见的约定是使用下划线作为私有变量和受保护变量的前缀。

答案 4 :(得分:0)

您可能需要查看以前的帖子How do I create an abstract base class in JavaScript?

在OOP和JavaScript上为您提供一些轻松阅读的几个网站,我假设您的新手是基于您所说的评论的OOP语言

http://mckoss.com/jscript/object.htm

http://www.codeproject.com/KB/aspnet/JsOOP1.aspx

http://www.javascriptkit.com/javatutors/oopjs.shtml