【问题标题】:Structuring JavaScript: Writing a basic validator构建 JavaScript:编写一个基本的验证器
【发布时间】:2012-10-04 16:00:02
【问题描述】:

我正在尝试清理我的 JavaScript 代码,这样我就可以停止编写意大利面条式代码并拥有一些更整体的结构。我想通过编写一个简单的表单验证器来测试我的技能。但是,我已经卡住了。

这是我目前的代码:

(function($, window, undefined) {
    var Form = function($el) {
        this.$el = $el;
        this.fields = {};

        this.prototype.validate = function() {
            this.getFields();    
        }

        this.prototype.getFields = function() {
            console.log("getting fields");
        }

        return {
            validate: this.validate
        }
    };

    window.Form = Form;
})(jQuery, window);


$(function() {

    var form = new Form('#form-newsletter');
    form.validate();

});

关于这个的几个问题。

我将 Form 变量包装在一个自执行函数中,并传入三个参数。 jQuery、window 和 undefined 以确保它始终未定义。我不会撒谎,这就是我学会这样做的方式,我不是 100% 确定我为什么这样做。这是不好的做法还是我可以以某种方式改进?然后我通过将 Form 变量附加到窗口来公开它。

Form var 中,我设置了一些属性(我们是这样称呼它们的吗?)并且我有几个方法。我只在 return 语句中公开了 validate 方法。这样可以吗?

然后是我卡住的部分。我希望validate() 像一个初始化函数,它的任务是验证表单。 Validate 应该调用 getFields 函数来解析表单字段并将它们放入 fields 对象中。但是,我似乎无法让它工作。当我调用this.getFields()this.prototype.getFields()Form.getFields 时,它不起作用。这是因为此函数中的this 与 Form 对象不同(这里的措辞正确吗?)?我应该在表单函数的开头加上this.self = this 之类的东西吗?

我也想知道是否可以将这些方法附加到原型中。有理由不这样做吗?

我正在努力学习;我读过的大多数关于 JavaScript 的书都集中在基础知识上:Dog 类继承自 Mammal 类。但是,据我所知,他们并没有真正帮助我解决此类问题。是否有任何书籍、教程、截屏视频可以帮助我更好地理解这些概念?

编辑:

假设我想将我的脚本分组到一个公共命名空间下:我可以这样做

var MyStuff = {};

MyStuff.Utilities = { // stuff };
MyStuff.Form = function() { // stuff };

但是,如果我想将它们放入单独的文件中,例如 mystuff-form.jsmystuff-utilities.js,我该怎么做?我在哪里声明命名空间变量var MyStuff = {}?在我这样做之后,我可以将我的表单和实用程序附加到上面,对吗?我很难创建一个只有var MyStuff = {}; window.MyStuff = MyStuffMyStuff.js 文件,可以吗?

【问题讨论】:

    标签: javascript oop prototype encapsulation


    【解决方案1】:

    您混淆了构造函数和可以从中创建的对象。原型的思想是你在构造函数的.prototype 属性上设置函数,然后你通过构造函数创建的每个对象都可以访问这些函数。

    在构造函数内部,this 指的是正在创建的对象。在您的情况下,您正在对此类对象的原型进行设置 - 但该属性不存在。要在构造函数的 .prototype 上设置属性,jQuery 允许使用 $.extend 的简洁语法:

    // extend constructor's prototype with functions
    
    $.extend(Form.prototype, {
        validate: function() {
            this.getFields();    
        },
    
        getFields: function() {
            console.log("getting fields");
        }
    });
    

    现在,任何对象都有可用的.validate() 函数。

    此外,您正在从构造函数返回一个新对象。你不需要;它甚至会破坏继承/原型的想法。

    另外 - 您编码 this.$el = $el,但在您的情况下,您传递了一个选择器字符串,所以我猜您希望 $($el) 将其转换为 jQuery 集(也许还重命名参数)。

    最后,匿名函数不需要传递所有这些参数:

    • jQuery -> $ - 如果页面处于 jQuery.noConflict() 模式,这很有用 - 您可以在函数中以 $ 的形式访问 jQuery。
    • window -> window - 没有真正的目的。 window 甚至是只读的,所以不会改变。
    • undefined - 在现代浏览器中,这是只读的,所以不需要传递它。在较旧的浏览器中,如果您 a) 不通过它,并且 b) 您页面上的某些脚本更改 undefined,它只会导致冲突。当然,这并不重要,但像你一样通过它并没有什么坏处。

    http://jsfiddle.net/4UNAp/

    【讨论】:

    • 谢谢。这非常有帮助,我想我现在明白了。我确实混淆了不同的概念。我用我想知道的另一件事更新了我的问题,但我接受了这个答案,因为它对我有很大帮助。
    • @cabaret:您可以在两个文件的顶部编码window.MyStuff = window.MyStuff || {};。它会将其设置为现有属性(如果已经定义,那么实际上什么都不做),或者设置为一个新对象。
    猜你喜欢
    • 2015-11-15
    • 2013-05-05
    • 2014-01-17
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多