如何编写可重用的 Javascript?
Posted
技术标签:
【中文标题】如何编写可重用的 Javascript?【英文标题】:How can I write reusable Javascript? 【发布时间】:2011-02-06 05:24:24 【问题描述】:我已经开始将我的函数包装在对象中,例如:
var Search =
carSearch: function(color)
,
peopleSearch: function(name)
,
...
这对可读性有很大帮助,但我仍然遇到可重用性的问题。更具体地说,困难在于两个方面:
接收参数。很多时候,我会有一个带有多个输入字段的搜索屏幕和一个调用 javascript 搜索功能的按钮。我必须在按钮的 onclick 中放置一堆代码以检索然后将输入字段中的值军事化到函数调用中,或者我必须对 html 输入字段名称/ID 进行硬编码,以便随后可以检索它们使用 Javascript。我为此确定的解决方案是将字段名称/ID 传递给函数,然后它使用该函数从输入字段中检索值。这很简单,但看起来确实不合适。
返回值。大多数 Javascript 调用的效果往往是屏幕上的某些视觉效果直接发生变化,或者是调用中执行的另一个操作的结果。当我将这些屏幕更改效果放在函数的末尾时,可重用性就很不错了。例如,搜索完成后,我需要在屏幕上显示结果。
其他人如何处理这些问题?思考上限让我相信我需要在我的应用程序中的每次使用和我创建的将在应用程序范围内使用的通用方法之间有一个特定于页面的 Javascript 层。使用前面的示例,我将有一个搜索按钮,其 onclick 调用 myPageSpecificSearchFunction,其中搜索字段 ID/名称是硬编码的,它编组参数并调用通用搜索函数。通用函数将仅返回数据/对象/变量,不会直接读取 DOM 或对 DOM 进行任何更改。然后,特定于页面的搜索功能将接收此数据并适当地更改 DOM。
我是在正确的道路上还是有更好的模式来处理 Javascript 对象/方法的重用?
【问题讨论】:
建议将其设为社区 wiki,它非常主观。 【参考方案1】:Javascript 非常灵活,这意味着您的设计尤为重要,因为您可以以多种不同的方式做事。这可能就是让 Javascript 感觉不太适合重用性的原因。
声明对象(函数/类)然后为它们命名空间有几种不同的表示法。了解这些差异很重要。正如评论中提到的“命名空间轻而易举” - 是一个很好的起点。
我无法在此回复中走得足够远,只能解释,所以我建议购买这些书:
Pro JavaScript Design Patterns
Pro Javascript techniques
【讨论】:
【参考方案2】:我开始使用module pattern,但后来开始使用jQuery plugins 做所有事情。插件允许传递页面特定的选项。
使用 jQuery 还可以让您重新思考识别搜索词并找到它们的值的方式。您可以考虑为每个输入添加一个类,并使用该类来避免专门命名每个输入。
【讨论】:
【参考方案3】:基本模式
就您的基本模式而言,我是否可以建议修改您的结构以使用模块模式和命名函数:
var Search = (function()
var pubs = ;
pubs.carSearch = carSearch;
function carSearch(color)
pubs.peopleSearch = peopleSearch;
function peopleSearch(name)
return pubs;
)();
是的,这看起来更复杂,但这部分是因为不涉及辅助函数。请注意,现在,每个函数都有一个名称(您以前的函数是匿名的;它们绑定的属性有名称,但函数没有,这对调试器中调用堆栈的显示等有影响)。使用模块模式还使您能够拥有只有 Search
对象中的函数才能访问的完全私有函数。 (只需在大匿名函数中声明函数,不要将它们添加到 pubs
。)更多关于我的理由(优点和缺点,以及为什么不能将函数声明和属性分配结合起来)@987654321 @。
获取参数
我非常非常喜欢Prototype 中的一个函数是Form#serialize
函数,它遍历表单元素并根据字段名称为每个字段构建一个具有属性的普通对象。 (Prototype 当前的 - 1.6.1 - 实现存在一个问题,即它不保留字段的顺序,但令人惊讶的是,这种情况很少出现。)听起来你会得到很好的服务通过这样的东西,它们并不难建造;那么您的业务逻辑正在处理具有根据其相关内容命名的属性的对象,并且不了解实际表单本身。
返回值/混合 UI 和逻辑
我倾向于将应用程序视为对象以及它们之间的连接和交互。所以我倾向于创造:
代表业务模型等的对象,与接口无关(当然,业务模型几乎可以肯定部分由接口驱动)。这些对象在一个地方定义,但同时使用客户端和服务器端(是的,我使用 JavaScript 服务器端),并且在设计时考虑了序列化(在我的情况下是通过 JSON),因此我可以来回发送它们很容易。 知道如何使用它们来更新底层存储的对象服务器端(因为我倾向于处理具有底层存储的项目),并且 知道如何使用该信息呈现到 UI 的客户端对象。(我知道,几乎不是原创!)我尝试保持存储和渲染对象的通用性,因此它们主要通过查看业务对象的公共属性(几乎是所有属性;我不使用)来工作像 Crockford 这样的模式可以让你真正隐藏数据,我觉得它们太贵了)。实用主义意味着有时存储或渲染对象只需要知道他们正在处理什么,具体来说,但我会尽量保持通用性。
【讨论】:
非常有趣的东西。我不确定服务器端 javascript 对我来说有多可行(你能与我们分享你为此使用的技术吗?),但我会研究你提到的模块模式和原型方法。 @Renderln:(奇怪,我之前回答过,但它已经消失了。)现在我的很多应用程序工作都在使用 IIS 的 Intranet 上,因为应用程序运行的平台,所以我只是使用JScript(有时是 JScript.Net,但主要是 JScript)。在我的其他一些工作中,我在 Java 堆栈之上使用 Rhino(Rhino 是 JVM 的 JS)。但还有其他选择,例如 Google 的速度极快的 V8 解释器/编译器(他们在 Chrome 中使用的那个),它可以作为 Apache 模块从至少一个和我认为两个项目中获得。 CouchDB 和其他人在服务器端使用 SpiderMonkey。你明白了。 :-) @T.J.Crowder 我对这种设计有疑问。我实际上是在课堂上思考如何以可重用的方式管理它们。您是否能够使用该模式创建属于同一“类”的多个对象? @kitimenpolku:我不认为我会使用上面的那个模式。 Here's a page 展示了创建“类”的强大模式。它是在比较使用和不使用我的帮助脚本Lineage
的情况下进行的,但您不需要使用该脚本(尽管欢迎您使用),比较页面显示您无需这样做。跨度>
@KennyEvitt:谢谢,var pubs;
应该是 var pubs = ;
固定的。以上是关于如何编写可重用的 Javascript?的主要内容,如果未能解决你的问题,请参考以下文章