构建JavaScript:编写基本验证器

时间:2012-10-04 16:00:02

标签: javascript oop prototype encapsulation

我正在尝试清理我的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,以确保它始终未定义。我不会撒谎,这就是我学会这样做的方式,我不是百分之百确定为什么我这样做。这是不好的做法还是我能以某种方式改进?然后我通过将Form变量附加到窗口来公开它。

Form var中,我设置了一些属性(我们如何调用它们?)我有几种方法。我只在return语句中公开了validate方法。这没关系吗?

然后是我卡住的部分。我希望validate()像初始化函数一样,它具有验证表单的任务。 Validate应调用getFields函数来解析表单字段并将它们放入fields对象中。但是,我似乎无法实现这一目标。当我致电this.getFields()this.prototype.getFields()Form.getFields时,它无效。这是因为此函数中的this与Form对象不同(这里的措辞正确吗?)?我应该在Form函数的开头添加this.self = this之类的内容吗?

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

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

编辑:

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

var MyStuff = {};

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

但是,如果我想将这些文件放入单独的文件中,例如mystuff-form.jsmystuff-utilities.js,我该如何处理呢?我在哪里声明命名空间var var MyStuff = {}?在我这样做之后,我可以将表单和实用程序附加到那个,对吧?我几乎无法制作MyStuff.js只有var MyStuff = {}; window.MyStuff = MyStuff的文件,可以吗?

1 个答案:

答案 0 :(得分:2)

您可能会混淆构造函数和可以从中创建的对象。原型的想法是你在构造函数的.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/