0

我知道 javascript 函数完全能够调用其他函数。我已经使用过几次了。

目前我正在编写一个脚本,该脚本将找到某个标签的 html 元素,并根据它的标签类型添加一些文本。

function foo() {
dealWithH1();
dealWithH2();           
dealWithH3();
etc...          
}

我已经对这样的功能进行了一些搜索,但我似乎无法找到一个明确的、一致的答案来确定这是否是一种好的做法。我喜欢这种方式,因为有很多函数调用要进行,而且它保持井井有条。我只是想确保在我深入研究之前确保做这样的事情没有什么明显的问题。该函数foo()没有任何用途,只是被调用,onLoad然后调用所有这些其他函数。

这可以吗,还是有更受鼓励的方法来完成这项工作?

4

3 回答 3

4

It's perfectly reasonable to create a pseudo-DSL of operations that are composed of functions.

Based on your description of what the dealWith... functions do, though, I think you might want to generalize your functions more, something like:

function foo() {
    tagInsert('h1', 'Text to append to h1 tag');
    tagInsert('h2', 'Text to append to h2 tag');
    tagInsert('h3', 'Text to append to h3 tag');
}

Now that the essence of the function has been distilled (append text to all tags of a specified type), and the variables of the function have been parameterized (the type of tag and the text to append), you could just as easily do something like:

var tags = {
    'h1': {
        'en': 'Hello',
        'es': 'Hola',
        'sr@latin': 'Zdravo'
    },
    'h2': {
        'en': 'Goodbye',
        'es': 'Adios',
        'sr@latin': 'Do vidjenja'
    },
    'h3': {
        'en': 'Green',
        'es'; 'Verde',
        'sr@latin': 'Zelena'
    }
};
function foo(locale) {
    for(var tag in tags) {
        tagInsert(tag, tags[tag][locale]);
    }
}

Composability of functions is greatly improved when as much about the operation you will perform is deferred until the function is actually called -- you can then use the exact same function to now not just append a fixed set of text to the tags, but to do so in whatever language the user prefers to use.

This flexibility can of course be taken to absurd lengths and you'd never get anything done, but it's good to think of your function as a set operator: what is the input to your function (declared explicitly as a variable or implicitly by accessing a global) and what operation is performed to produce the new output set?

If it doesn't take much extra effort to write the function in the generic way versus the specific case you're dealing with, then write it that way and you can re-use that function whenever you need to do a similar action but with different inputs.

Remember...

Don't take my tagInsert definition at face value, I know barely anything about what you're actually trying to do, and maybe that generalization doesn't really make sense. The point is that you as the developer should have a better idea of what you're trying to accomplish.

If you follow Larry Wall's Virtues of a Programmer, you should be trying to minimize the amount of extra work you have to do, and your functions will reach the right degree of composability versus complexity.

Functions calling functions is the whole point of a function -- you avoid the need to rewrite it over and over again; just dividing a massive imperative declaration of actions to perform into a series of functions is not the point of a function. What are the repetitive patterns in the imperative code and how can you be as lazy as possible?

于 2012-06-05T18:43:48.220 回答
3

假设你写的代码不是完全的伪代码,我绝对不会那样做:你会用很多不同的函数污染全局范围。您可以使用闭包将这些函数包装在本地范围内,或者使它们成为对象的方法。

此外,似乎dealWithTagH1dealWithTagH2等等,也有在里面寻找这些特定标签并修改它们的目的。这是你可以推断的逻辑。所以,你应该有一些东西可以得到你感兴趣的所有类型的标签,然后调用这些dealWith函数。这样,您只有一个正在寻找标签的代码,以及处理该特定标签的不同功能。你以这种方式解耦了更多的逻辑。如果您想以一种极端的方式进行说明,则可以使用诸如策略模式之类的东西。

我还将修改命名,给每个“策略”一个更好dealWithTagH1的名称(它非常通用,阅读该代码的开发人员对实际实施的策略没有任何暗示)。

于 2012-06-05T18:37:46.000 回答
2

在几乎任何主流语言中,函数/方法都很便宜,并且从维护和可读性的角度来看,具有尽可能小的和内聚的函数是一个很好的实践。您不应该害怕创建函数、提取它们、在层次结构中调用它们(一个函数调用另一个函数,而后者又调用第三个函数)。您还应该学习如何使用

函数(包括匿名函数和闭包)是 JavaScript 中的主要构建块,它们无处不在,例如事件处理程序和回调。

避免比屏幕更长的功能(有人说 10 行,一些 5 - 只是保持简短)。还可以使用函数来减少重复。例如,有些事情告诉我,你们所有人dealWithH*()都非常相似。关于什么:

function foo() {
  dealWithTag('h1');
  dealWithTag('h2');           
  dealWithTag('h3');
  //etc...          
}

当然,在您的情况下,单独的函数可能是一个更好的主意,但只需从抽象的角度考虑并尝试概括问题。

于 2012-06-05T18:33:41.477 回答