一個表單驗證引起的深思!!!

需求

實現一個表單驗證,用於驗證用戶名,郵箱,密碼等。javascript

function checkName() {
    // 驗證用戶名
}
function checkEmail() {
    // 驗證郵箱
}
function checkPassword() {
    // 驗證密碼
}
...
複製代碼

經過上面咱們書寫的函數實現了咱們的需求。 可是咱們寫完以後,會不會考慮一個問題,這些函數都是變量,並且是全局變量!java

函數的另一種形式

var checkName = function () {
    // 驗證用戶名
}
var checkEmail = function () {
    // 驗證郵箱
}
var checkPassword = function () {
    // 驗證密碼
}
...
複製代碼

兩種寫法實際上是一致的,都是聲明瞭三個所有變量,功能上沒啥問題,可是在團隊開發中,咱們寫代碼的時候就須要三思後行了,不能只考慮本身,也要考慮不影響到其餘人,若是別人也定義了一樣的方法就會覆蓋掉原有的功能。若是咱們定義了不少方法,這種互相覆蓋的問題是很不容易被發現的。函數

那麼咱們應該如何避免這種狀況呢?優化

使用對象收編變量

對象都擁有屬性和方法,而若是咱們要訪問他的屬性或者方法時,可經過點語法遍歷查詢獲得。所以咱們的代碼能夠修改成:ui

var CheckObject = {
    checkName: function () {
        // 驗證用戶名
    },
    checkEmail: function () {
        // 驗證郵箱
    },
    checkPassword: function () {
        // 驗證密碼
    }
    ...
}
複製代碼

此時咱們將搜有的方法都放在CheckObject這個對象裏面,咱們只聲明瞭一個變量,咱們使用也很是簡單,好比檢測用戶名CheckObject.checkName(),這樣只是在咱們以前使用函數式前面加了一個對象名稱。this

固然還有另一種形式。spa

對象的另一種形式

在javascript中,函數也是對象的一種,因此咱們能夠這樣寫:prototype

var CheckObject = function () {};
CheckObject.checkName = function () {
    // 驗證用戶名
}
CheckObject.checkEmail = function () {
    // 驗證郵箱
}
CheckObject.checkPassword = function () {
    // 驗證密碼
}
...
複製代碼

使用和前面的方式是同樣的,可是這樣寫雖然知足了咱們本身的需求,但當別人想用咱們寫的方法時就有些麻煩了,由於咱們寫的這個對象沒辦法進行復制,也就是經過new關鍵字建立的新的對象不會繼承這些方法。代碼規範

真假對象

若是咱們想簡單的進行復制一下,那麼咱們能夠這麼寫:code

var CheckObject = function () {
    return {
        checkName: function () {
            // 驗證用戶名
        },
        checkEmail: function () {
            // 驗證郵箱
        },
        checkPassword: function () {
            // 驗證密碼
        }
        ...
    }
}
複製代碼

咱們上面寫的代碼,看上去是複製了,當每次調用這個函數的時候,把咱們以前寫的這個對象返回出來,當別人每次調用的時候都返回了一個新的對象,這樣執行過程當中明面是CheckObject對象,可其實是返回的新對象,這樣每一個人在使用的時候就互不影響了。好比咱們想要驗證郵箱:

var a = CheckObject();
a.checkEmail();
複製代碼

雖然上面咱們經過建立新對象的需求,可是這並非一個真正意義上類的建立方式,而且建立的對象a和CheckObject沒有任何關係(返回出來的對象自己就和CheckObject對象無關),因此咱們對代碼再次進行需改:

var CheckObject = function () {
    this.checkName = function () {
        // 驗證用戶名
    }
    this.checkEmail = function () {
        // 驗證郵箱
    }
    this.checkPassword = function () {
        // 驗證密碼
    }
}
複製代碼

上面咱們實現的CheckObject就能夠看做是一個類,咱們能夠經過new 關鍵字來建立

var a = new CheckObject()
a.checkName()
複製代碼

這樣每一個使用者在使用CheckObject時,經過對CheckObject進行實例,那麼每一個人都會有屬於本身的方法,而且不相互影響。

更優化的方案

咱們將全部的方法都放在了函數內部,經過this定義,因此每次經過new關鍵字建立對象的時候,新建立的對象都會對類的this上的屬性進行復制。因此這些建立的方法都會都本身的一套方法,然而有時候這麼作形成的消耗是很奢侈的,咱們須要處理一下:

var CheckObject = function () {}
CheckObject.prototype.checkName = function () {
    // 驗證用戶名
}
CheckObject.prototype.checkEmail = function () {
    // 驗證郵箱
}
CheckObject.prototype.checkPassword = function () {
    // 驗證密碼
}
...
複製代碼

這樣建立對象實例的時候,建立出來的對象所擁有的方法就都是一個了,由於它們都依賴的prototype原型依次尋找,而找到的方法是同一個,它們都綁定在CheckObject對象的原型上。這種方式須要寫不少遍prototype,咱們也能夠這麼寫:

var CheckObject = function () {}
CheckObject.prototype = {
    checkName: function () {
        // 驗證用戶名
    },
    checkEmail: function () {
        // 驗證郵箱
    },
    checkPassword: function () {
        // 驗證密碼
    }
    ...
}
複製代碼

可是有一點須要記住,這兩種方式不能混合使用,若是混用的話,後面的對象的原型爲對象賦值新對象的時候,它會將以前對prototype對象賦值的方法覆蓋掉!!

這裏還有一點須要你們關注的是前者實例的constructor是ƒ (){}後者指向的是ƒ Object() { [native code] }

實現鏈式調用

咱們上面寫的代碼在使用的時候:

var a = new CheckObject()
a.checkName()
a.checkEmail()
a.checkPassword()
複製代碼

咱們須要寫多遍a對象,若是咱們在聲明的每一個方法末尾將當前的對象返回,那麼咱們就能夠進行鏈式調用了!

var CheckObject = function () {}
CheckObject.prototype = {
    checkName: function () {
        // 驗證用戶名
        return this;
    },
    checkEmail: function () {
        // 驗證郵箱
        return this;
    },
    checkPassword: function () {
        // 驗證密碼
        return this;
    }
    ...
}
複製代碼

這樣咱們在使用的時候就能夠寫成:

CheckObject.checkName().checkEmail().checkPassword()
複製代碼

Prototype

有興趣的同窗能夠看一下這篇文章 原型與原型鏈

可能在上面的實現中,你們可能內心會有這種實現思路:

Function.prototype.checkName = functionn () {
    // 驗證用戶名
}
var f = new Function()
f.checkName()
複製代碼

這樣作實際上是不可取的,由於這樣作污染了原聲對象Function,別人建立的函數也會被污染,形成沒必要要的開銷,其實咱們能夠這樣作:

Function.prototype.addMethod = function (name, fn) {
    this[name] = fn
}
複製代碼

這樣的話, 咱們想添加業務邏輯的時候就能夠這樣作:

var methods = new Function()
methods.addMethod('checkName', function () {
    // 驗證用戶名
})
methods.addMethod('checkEmail', function () {
    // 驗證郵箱
})
methods.checkName()
methods.checkEmail()
複製代碼

固然咱們還能夠實現鏈式添加方法:

Function.prototype.addMethod = function (name, fn) {
    this[name] = fn;
    return this;
}

var methods = new Function()
methods.addMethod('checkName', function () {
    //驗證用戶名
    return this;
}).addMethod('checkEmail', function () {
    // 驗證郵箱
    return this;
})

// 調用
methods.checkName().checkEmail()
複製代碼

最後

JavaScript是一門靈活的語言,這由於這種靈活性,因此每一個人均可能會寫出不一樣風格的代碼,這是JavaScript給予咱們的財富,不過在團隊開發中咱們謹慎發揮,儘可能保持團隊開發代碼風格的一致性,這也是團隊代碼易開發、可維護以及代碼規範的必要條件!

文章同步更新在個人我的公衆號與個人我的博客

相關文章
相關標籤/搜索