【问题标题】:Splitting code up into functions将代码拆分为函数
【发布时间】:2012-11-07 14:47:06
【问题描述】:

由于性能和其他问题,我想将我的代码拆分为单独的函数,就像以前它只是一个大的“.ready”函数一样。

我是 javaScript/jquery 的新手,但我想我会自己尝试一下。我已经完全按照我认为的方式完成了,但是我的控制台告诉我事情是未定义的,所以我猜我的事情超出了范围。我已经更详细地阅读了它,但仍然没有得到任何地方。

我的代码目前工作正常,但我想养成干净编码的习惯。有人可以指出我哪里出错了,这样我就可以继续自己了?

这是我到目前为止的一个例子

//Global variables
var randomWord = [];
var listOfWords = [];
var populationNumber = [];
var attemptNumber = [];
var completionNumber = [];
var gridSize = [];

generateGrid();

startMusic();

randomizeReward();


//Click event to start the game
$(".start-btn-wrapper").click(function () {
    startplay();
});
//Click event to restart the game
$(".restart-btn").click(function () {
    restartplay();
});

谢谢

小提琴:http://jsfiddle.net/QYaGP/

摆弄 HTML:http://jsfiddle.net/QYaGP/1/

【问题讨论】:

  • 在没有 HTML 的 jsfiddle 中不是一个完整的工作示例,但我的直接猜测是:您的“全局范围”变量仅对就绪状态是全局的。 ready 之外的函数无法访问这些变量。将它们移到 jquery ready 函数上方,这样它们就真正是全局的,并且其他函数可以访问它们。
  • 好的,我会试试 Eli Gassert
  • 了解 JavaScript 变量作用域并阅读 functional programming
  • 没什么区别我害怕@EliGassert
  • 将 HTML 添加到 jsfiddle 以使其成为一个功能示例,这样我们就可以真正看到发生了什么。 JS 太多,无法仅通过视觉解析并确定问题。

标签: javascript jquery oop function


【解决方案1】:

如果您担心性能,我会考虑使用 AngularJS 等框架。您可以注入模块化代码。更好的是,使用 MVC,您的视图将绑定到您的模型,因此通过更改模型,视图会自动更新自身。

另外,停止使用类选择器。使用 ID 选择器。他们要快得多。您还想预加载选择器(即使使用类选择器)。这样你只搜索 DOM 一次:

var ele = $('#elementId');

$(ele).doSomething();

这样,您就有了对 DOM 元素的引用。您可以使用数据结构将所有引用存储在全局范围之外:

var elementReferences = {}; //declaration
elementReferences.mainPage = {}; //use
elementReferences.mainPage.root = $('#mainPage'); //load the root div of a page segment
elementReferences.mainPage.title =   $(elementReferences.mainPage.root).children('#title'); //load the title 

elementReference.mainPage.form = $(elementReferences.mainPage.root).children('#form'); //load the form

现在你可以这样做了:

$(elementReference.mainPage.form).whatever();

它不必在 DOM 中搜索元素。这对于大型应用程序尤其有用。

如果您在 document.ready 中放置一个函数,按照您的小提琴,您只能在 document.ready 调用范围内访问该函数。您真的希望能够在需要的范围内根据需要动态加载/卸载函数,这就是 angularjs 发挥作用的地方。

在大多数情况下,您还希望从全局范围中删除您的函数和变量,并将它们放入按其依赖项和使用排序的容器中。这是面向对象编程 101。与其让一堆数组位于全局范围内,否则它们可能会被其他开发人员错误地覆盖,您希望将它们放在一个容器中:

var arrays = {}; //create the object

arrays.whatever1 = [];
arrays.whatever2 = [];

显然,您可能需要一个比“数组”更具描述性的名称。函数的工作方式相同:

var ajax = {}; //ajax object
var ajax.get = function(){
};
var ajax.post = function(){
};
var ajax.delete = function(){
};

这通常会促进更简洁的代码,这些代码更可重用且更易于维护。您想在实际开始开发之前花费大量时间编写一个完整记录整体架构的规范。如果你能帮上忙,千万不要急于求成。花时间彻底研究和规划大局以及一切如何组合在一起,而不是试图随心所欲地弄清楚它。这样做可以减少重新发明轮子的时间。

它是由 google 开发的,所以应该已经存在了一段时间。我不确定您是否是负责系统架构的人,但如果您的公司存在性能/可重用性问题,那么绝对值得一看。我非常乐意向您介绍我在软件架构和工程方面所知道的大部分内容。如果你有兴趣,就给我留言。总是乐于提供帮助!

【讨论】:

    【解决方案2】:

    您需要开始将一些信息传递到您定义的函数中。如果您的函数都没有参数,那么您将不得不使用全局定义的变量、对 jquery 选择的硬编码引用等才能完成任何事情。

    举个例子,你有一个函数

    function replaySound() {
        $("#hintSound").attr('src', listOfWords[randomWord].hintSound);
        hintSound.play();
    }
    

    这实际上是通过元素#hintSound 播放listOfWords[randomWord] 中详述的声音。您可以通过以下方式做到这一点:

    function playSound(selector, wordlistEntry) {
        $(selector).attr('src', wordlistEntry.hintSound);
        $(selector)[0].play();
    }
    

    然后你不会调用replaySound(),而是调用:

    playSound('#hintSound', listOfWords[randomWord]);
    

    这样,你想要的行为被封装在函数中,但是细节,即你需要的数据,是通过参数传入的。这使您可以重用该函数以使用任何选择器播放任何声音,而不仅仅是#hintSound

    您会发现,您需要开始在调用它的代码中而不是在函数中选择函数的作用。这很好,因为您试图实现的上下文存在于调用代码中,而不是函数中。这被称为“关注点分离”;您尝试将给定事物的逻辑限制在一个区域,而不是将其分散在许多功能中。但是您仍然希望函数允许您封装行为。这使您可以干净而轻松地更改行为,而不必在每次逻辑的某些部分更改时都重写所有内容。

    结果应该是你发现几个函数实际上做了同样的事情,但细节不同,所以你可以只使用一个函数并重用它。这就是不要重复自己的原则,这也很重要。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-20
      • 2017-08-28
      • 2021-06-02
      • 1970-01-01
      • 2020-01-30
      • 2014-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多