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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7477453/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 00:14:34  来源:igfitidea点击:

Best Practices for "Abstract" functions in JavaScript?

javascriptfunctional-programmingabstract-class

提问by Vivian River

I just wrote some JavaScript code that follows along with what I believe to be good practice for creating an object with closure and some functions:

我刚刚编写了一些 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'

I have no problem writing code like the previous snippet. I would like to write some code with functionality similar to a OOP "abstract" class. Here is the result of my effort:

我可以像前面的代码片段一样编写代码。我想编写一些功能类似于 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'

The above code snippet works, but it doesn't seem graceful. Perhaps I'm trying to force JavaScript (a functional language) to do something it isn't designed to do (object inheritance)

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

What is a good way to define an object in JavaScript so that a function of that object can be defined later?

在 JavaScript 中定义一个对象以便稍后可以定义该对象的函数的好方法是什么?

回答by SLaks

Just don't define the function.

只是不要定义函数。

Javascript is a duck-typedlanguage. If it looks like a duck and it quacks like a duck, it is a duck.
You don't need to do anything special to make this work; as long as the function exists when you call it, it will work fine.

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

If you call it on an instance that doesn't have the function, you'll get an error at the callsite.

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

回答by Juan Mendes

I agree with SLaks, there's no need to define the function, but I tend to anyway. That's because to me the important part is in the documentation. When somebody reads my class, I want it to be clear that you must implement these methods, what arguments will be passed and what should be returned.

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

This is from a file at work. There were multiple implementations of a feature with a base class that did the data loading at intervals.

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

/**
 * 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 Update

2019年更新

Use TypeScript if you can Declaring abstract method in TypeScript

如果可以在 TypeScript 中声明抽象方法,请使用 TypeScript

回答by Oliver Watkins

As our team is growing and our javascript project is getting more complex we have to start implementing OO features as well.

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

In our javascript 'abstract' method we simply throw an error, or pop up an alert. This is an example from out Page object:

在我们的 javascript 'abstract' 方法中,我们只是抛出一个错误,或者弹出一个警报。这是来自页面对象的示例:

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

In java world it is analagous to :

在 Java 世界中,它类似于:

public void abstract initialLoad();

The Java code gives a compile timeerror, however in the Javascript we would get a runtime error. (a dirty error dialog saying that an implementing object hasn't implemented that method yet).

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

We have a number of disparate teams that use the Page object; the philosophy of 'duck typing' absolutely does not cut it with us. Without these pseudo 'abstract' methods we have a general lack of API communication, and sometimes we get sabotaging of the super object (ie. because a user has no idea they are supposed to implement the method).

我们有许多不同的团队使用 Page 对象;“鸭子打字”的理念绝对不适合我们。如果没有这些伪“抽象”方法,我们将普遍缺乏 API 通信,有时我们会破坏超级对象(即,因为用户不知道他们应该实现该方法)。

I am tired of this 'duck typing' philosophy. I'm not sure if proponents have ever been in a complex Javascript project with 10+ developers.

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

回答by hugomg

If you don't find your way graceful there is probably a way to create some functions to stramline the process to make it look better. But back to the topic...

如果您觉得自己的方式不够优雅,那么可能有一种方法可以创建一些函数来精简流程,使其看起来更好。但是回到正题……

Yes, Javascript has builtin delegation, aka inheritance, via prototypes.

是的,Javascript 有内置的委托,也就是继承,通过原型

Given a prototypal object:

给定一个原型对象:

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

We can create a new object that inherits from it:

我们可以创建一个继承自它的新对象:

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

Just note, that doing things directly via Object.create is not always supported (old browsers, etc). The old (and some may say, normal) way do do stuff is via the funky newoperator (don′t think too much on the name - its confusing on purpose to distract the Java people)

请注意,并不总是支持直接通过 Object.create 执行操作(旧浏览器等)。旧的(有些人可能会说是正常的)做事的方式是通过时髦的new操作符(不要对这个名字想太多——它故意混淆了 Java 人的注意力)

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

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

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


An important difference to consider with prototypical inheritance is the lack of private variables. Only public variables can be inherited!Because of this, a common convention is to use underscore as a prefix for private and protected variables.

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

回答by Spider

You might want to take a look at this previous post How do I create an abstract base class in JavaScript?

您可能想看看之前的这篇文章如何在 JavaScript 中创建抽象基类?

Just a few sites for some light reading for you on OOP and JavaScript, I am assuming that your new to JavaScript as an OOP langauge based of a comment you said

只有几个网站可以让您轻松阅读有关 OOP 和 JavaScript 的内容,我假设您是根据您所说的评论将 JavaScript 作为 OOP 语言的新手

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

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

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

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

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

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