在JavaScript中为函数创建原型?

时间:2016-03-10 09:06:18

标签: javascript function oop object prototype

我可能做错了,但它似乎是一个使用原型的好地方。

我有一封电子邮件表格。将验证的该表单的每个输入都有一个对象。该对象的原型是......

var contactInput = function(placeholder, validateFuntion) {
  this.placeholder = placeholder;
  this.value = "";
  var error = true;
  this.setError = function(errorValue) {
    if(typeof(errorValue) === "boolean") {
      error = errorValue;
    } else {
      return false;
      console.log(".setError argument must be boolean.");
    }
  };
  this.getError = function() {
     return error;
  }
  var errorMessage = "";
    this.setErrorMessage = function(errorMessageValue) {
    if(typeof(errorMessageValue) === "string") {
      errorMessage = errorMessageValue;
    } else {
      return false;
      console.log(".setErrorMessage argument must be string.");
    }
  };
  this.getErrorMessage = function() {
     return errorMessage;
  }
  this.validateFunction = validateFunction;
}

我在这里遇到的问题与validateFunction属性有关。这些输入中有三个。它们的每个验证功能都非常相似。它们仅在操作方面有所不同,以验证值,以及错误时它们产生的错误消息。

其中一个看起来像这样......

function(inputValue) {
    if (inputValue === "") {
      this.error = true;
      this.errorMessage = "You did not provide a name.";
      return "error.png";
    } else if (inputValue.length > 50) {
      this.error = true;
      this.errorMessage = "Name must be under 50 characters.";
      return "error.png";
    } else {
      this.error = false;
      return "tick.png";
    }
      }

另一个看起来像这样......

function(inputValue) {
    if (inputValue === "") {
      this.error = true;
      this.errorMessage = "You did not provide an email.";
      return "error.png";
    } else if ( !/(.+)@(.+){2,}\.(.+){2,}/.test(inputValue) ) {
      this.error = true;
      this.errorMessage = "The email you provided was invalid.";
      return "error.png";
    } else {
      this.error = false;
      return "tick.png";
    }
      }

我想为验证函数创建一个原型,然后我可以创建三个验证函数实例。然后我将使用原型作为输入(我已经拥有的)创建输入的三个实例,使用我创建的验证函数的实例来设置输入实例的validateFunction方法。

我无法想到如何实现它,或者是否应该以这种方式完成它。即使它不应该完成,我将如何实现这一目标?

1 个答案:

答案 0 :(得分:0)

首先,你的术语有点令人困惑,我不会在这里打电话给#34;函数的原型"。

Prototype是一个对象,用作创建其他对象的原型。 在javascript中,您恰好使用function作为对象的构造函数。

关于您的实施的几点注意事项:

  1. 返回后的代码将永远不会被执行。并且console.log是一个告知错误的错误方法(最好抛出错误):

    } else {
      return false;
      console.log(".setError argument must be boolean.");
    }
    
  2. 就OOP而言,拥有getter和setter并不好,这样就可以将对象状态暴露给世界。更好的方法是将对象视为微型计算机,黑盒子,你可以要求做一些工作。 所有初始化数据都传递给构造函数,因此您不需要setter,并且对象内部的数据相关工作由对象完成,因此您也不需要getter。

  3. 有两种方法可以实现稍微不同的行为 - 继承,其中子类实现差异或组合,其中差异被移动到另一个对象。 使用方法取决于具体情况。

  4. 实现输入的一种可能方法是使用继承:

    function ContactInput(selector, placeholder) {
      // properties are prefixed with underscore to notify the programmer that they are
      // 'private' (should not be accessed outside of this class or subclasses)
      this._element = document.querySelector(selector);
      this._placeholder = placeholder;
    }
    
    ContactInput.prototype.validate() {
        // this should be implemented in child classes
        throw 'Not implemented';
    }
    
    // Private method (prefixed with underscore), also to be used only by this object
    ContactInput.prototype._renderSuccess(message, image) {
        message = message || "";
        image = image || "tick.png";
        // show the success div near the element (actually it is better to use css, 
        // so it will be not necessary to pass the `tick.png` and `error.png`
        // around, you could just change the element's css class here to show the tick)
    }
    
    // Private
    ContactInput.prototype._renderError(message, image) {
        message = message || "Validation error";
        image = image || "error.png";
        // show the error div near the element
    }
    
    // Private
    ContactInput.prototype._getValue() {
        return this._element.value;
    }
    
    function NameInput(placeholder) {
        ContactInput.call(this, placeholder);
    }
    NameInput.prototype = Object.create(ContactInput.prototype);
    
    NameInput.prototype.validate() {
        var value = this._getValue();
        if (!value) {
            return this.renderError("You did not provide a name.", 'error.png');
        }
        if (value.length > 50) {
            return this.renderError("Name must be under 50 characters.", 'error.png');
        }
        return this.renderSuccess();
    }
    
    function EmailInput(placeholder) {
        ContactInput.call(this, placeholder);
    }
    EmailInput.prototype = Object.create(ContactInput.prototype);
    
    EmailInput.prototype.validate() {
        var value = this._getValue();
        if (!value) {
            return this.renderError("You did not provide an email.", 'error.png');
        }
        if ( !/(.+)@(.+){2,}\.(.+){2,}/.test(value) ) {
            return this.renderError("The email you provided was invalid.", 'error.png');
        }
        return this.renderSuccess();
    }
    

    我不确定你如何使用placeholder,所以我把它留在了基类中。 根据使用情况,它可能只是NameInput(或EmailInput)的属性。

    现在你可以这样做:

    var inputs = [
        new NameInput('x'),
        new EmailInput('y')
    ];
    inputs.forEach(function(input) {
        input.validate();
    });
    

    请注意,您不必在其他地方执行input->setError('xxx')input->getError('xxx')等操作。 您只需创建对象,为其提供一些数据,并让它根据此数据运行。