2016-03-10 61 views
1

我可能會做這個錯誤,但它似乎是一個使用原型的好地方。在JavaScript中爲函數創建原型?

我有一個電子郵件表格。將要驗證的該表單的每個輸入都有一個對象。該對象的原型是...

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方法。

我想不出如何完成它,或者甚至應該這樣做。即使不應該這樣做,我將如何實現這一目標?

+4

我不認爲你用典型的方式使用術語'prototype'。這聽起來更像是你想要的是一個公共/共享函數,你可以傳遞一些參數,而不是將大部分代碼複製到幾個大體相同但稍有不同的函數中。在Javascript中,這只是一個共享函數,而不是'prototype'。 – jfriend00

+0

@ jfriend00這也可以工作。不過,有幾個理由我想這樣做。如果這是可能的話,那麼各個功能將「持續」。這將使我能夠調用每個函數而不必提供多個參數。在這種情況下,它將我的論點數從5減少到1.不得不圍繞廢墟的整個觀點來爭論。 – Allenph

+1

您可以創建一個包含98%功能的通用函數體,然後創建三個shell函數,它們只會將正確的參數傳遞給您的常用函數。然後,你獲得兩全其美的好處。在一個共享函數中調用每個驗證器和公共代碼的簡單函數。僅供參考,這是基本的編程結構(將通用代碼分解爲共享函數)。如果這是你不熟悉的東西,那麼你可能會從某種編程課程中受益,因爲它會幫助你更多地瞭解這種類型的東西。 – jfriend00

回答

0

首先,您的術語有些混亂,我不會在這裏調用任何「函數的原型」。

原型是一個對象,被用作創建其他對象的原型。 在JavaScript中,恰好你使用function作爲對象的構造函數。

關於你實現幾個注意事項:

  1. 返回後的代碼永遠不會被執行。而console.log是一個糟糕的方式告知錯誤(更好地拋出一個錯誤):

    } else { 
        return false; 
        console.log(".setError argument must be boolean."); 
    } 
    
  2. 在OOP方面,它是不是好有getter和setter,這樣你揭露對象的狀態到世界。更好的辦法是把對象當作微型計算機,一個你可以要求做一些工作的黑盒子。 所有的初始化數據都被傳遞給構造函數,所以你不需要setter,並且與對象內的數據相關的工作是由對象完成的,所以你也不需要getters。

  3. 有兩種方法可以實現略有不同的行爲 - 繼承,其中子類實現區別或組合,其中區別被移到另一個對象。 要使用什麼取決於具體情況。

一個實現你輸入的可能的方式是這樣的,用繼承:

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')在其他一些地方。 您只需創建對象,給它一些數據並讓它根據這些數據來工作。