JavaScript设计模式(1)-灵活的JS写法

一,开篇

JavaScript是一种非常灵活的语言,在js的世界里,函数是"一等公民"
近几年前端迅速崛起,各种js框架相继诞生,同时js也逐步成为了"全栈"领域

为了了解JS设计模式,首先需要掌握JS的一些基础写法

二,JS的多种写法

需求是写关于用户名,密码,邮箱的验证方法

1,小白写法(不推荐)

function checkUserName(){}
function checkPassword(){}
function checkEmail(){}

等同:

var checkUserName = function(){}
var checkPassword = function(){}
var checkEmail = function(){}
之所以称之为小白写法,并不是因为这样写是最简单的,而是因为这样写是"错的"
这种写法污染了全局变量,在多人协作的团队开发的项目中存在被覆盖的风险

2,对象收编变量

var checkUserInfo = {
    checkUserName : function(){},
    checkPassword : function(){},
    checkEmail : function(){}
}

checkUserInfo.checkUserName();

等同:

var checkUserInfo = {};
checkUserInfo.checkUserName = function(){}
checkUserInfo.checkPassword = function(){}
checkUserInfo.checkEmail = function(){}

checkUserInfo.checkUserName();
相比于小白写法,这种写法的好处是将属性或方法收编到一个对象中,
相当于为方法添加了自己的一个作用域
首先并没有污染全局,其次也极大程度的避免了被覆盖的风险

3,函数返回对象

var CheckUserInfo = function(){
    return {
        checkUserName : function(){},
        checkPassword : function(){},
        checkEmail : function(){}
    }
}
var checkUserInfo = CheckUserInfo();
checkUserInfo.checkUserName();
这种写法首先使用了对象收编函数的思想,将3个check函收编到了对象中
而获取这个对象时通过函数的返回来获取的
注意这里声明的函数变量名首字母是大写的CheckUserInfo,这里具有一个"类"的概念
每次调用function都会返回一个新对象,互不影响

4,类的写法

var CheckUserInfo = function(){
    this.checkUserName = function(){}
    this.checkPassword = function(){}
    this.checkEmail = function(){}
}

// 类的创建,调用方式
var checkUserInfo = new CheckUserInfo();
checkUserInfo.checkUserName();
使用了面向对象的方式,创建了一个用户信息校验的类,
使用前通过new关键字实例化这个类,新创建的对象会对类的this上的属性或方法进行复制,得到一个实例
这种写法的优势是,多个人通过new这个类,每个人都会得到一个单独的实例,互不影响
但作为一个通用的校验功能,每次new都创建一个新的实例,相当于浪费了内存

5,通过prototype原型添加属性(注意混用覆盖问题)

var CheckUserInfo = function(){};
CheckUserInfo.prototype.checkUserName = function(){}
CheckUserInfo.prototype.checkPassword = function(){}
CheckUserInfo.prototype.checkEmail = function(){}

var checkUserInfo = new CheckUserInfo();
checkUserInfo.checkUserName();

等同:

var CheckUserInfo = function(){};
CheckUserInfo.prototype = {
    checkUserName : function(){},
    checkPassword : function(){},
    checkEmail : function(){}
}

var checkUserInfo = new CheckUserInfo();
checkUserInfo.checkUserName();
通过prototype原型将属性或方法绑定到CheckUserInfo对象类的原型上
通过new创建实例时,创建的对象所拥有的方法都是一样的,以为需要依赖prototype原型依次查找
上边的第二种写法比第一种写法的优势在于不需要向第一种那样写很多次prototype
要注意的问题是两种写法不能混用,第二种为prototype原型赋值新的对象,会覆盖掉之前的prototype

6,链式写法
6.1对象收编属性或方法的链式写法:

var checkUserInfo = {
    checkUserName : function(){
        return this;
    },
    checkPassword : function(){
        return this;
    },
    checkEmail : function(){
        return this;
    }
}

checkUserInfo.checkUserName().checkPassword().checkEmail();

6.2类prototype原型对象的链式写法

var CheckUserInfo = function(){};
CheckUserInfo.prototype = {
    checkUserName : function(){
        return this;
    },
    checkPassword : function(){
        return this;
    },
    checkEmail : function(){
        return this;
    }
}

var checkUserInfo = new CheckUserInfo();
checkUserInfo.checkUserName().checkPassword().checkEmail()
通过对象收编属性或方法和类prototype原型对象的链式写法可以看到
每个function都返回了当前对象,所以才能实现链式调用
链式调用的优点很明显,可以在一句代码中连续调用多个方法进行校验

7,扩展原生Function对象方式(不推荐)

Function.prototype.checkUserName = function(){}

var func = function(){};
func.checkUserName();

var func1 = new Function(){};
func1.checkUserName();
这种写法拓展了JS原生的Function对象,将属性或方法添加到了Function对象的prototype原型对象中,
从而让所有的function都实现这个函数
但同时这种写法也污染JS原生Function对象,别人创建的函数也被污染了,而且还造成了不必要的开销

8,拓展原生Function对象-新增添加方法功能

// 拓展Function新增添加方法功能
Function.prototype.addMethod = function(name, fn){
    this[name] = fn;
}

// 创建function
var funcMothods = function(){};//或 var funcMothods = new Function();

// 添加方法
funcMothods.addMethod('checkUserName',function(){
    // checkUserName
})

// 调用方法
funcMothods.checkUserName();
这种拓展原生Function对象的方式,抽象了一个向function添加函数的方法,实现了对Function的拓展
当声明(或new)一个function时,function具有添加函数的功能
将需要的函数添加到当前function中,并使用

这种方式的好处是并没有污染原生Function(这种"污染"可以忽略),只是拓展了Function
通过addMethod添加的函数只对当前function生效,避免了不必要的开销

返回this,可以链式添加和链式调用

// 拓展Function新增添加方法功能
Function.prototype.addMethod = function(name, fn){
    this[name] = fn;
    return this;
}

// 创建function
var funcMothods = function(){};//或 var funcMothods = new Function();

// 链式添加方法
funcMothods.addMethod('checkUserName',function(){
    return this;
}).addMethod('checkPassword',function(){
    return this;
})

// 链式调用方法
funcMothods.checkUserName().checkPassword();

也可以用类的形式实现

// 拓展Function新增添加方法功能
Function.prototype.addMethod = function(name, fn){
    this[name] = fn;
    return this;
}

// 创建Mothods类
var Mothods = function(){};
// 添加方法(链式)
Mothods.addMethod('checkUserName',function(){
    // checkUserName
}).addMethod('checkPassword',function(){
    // checkPassword
});
// 类式使用
var methods = new Mothods();
methods.checkUserName();
首先拓展了原生Function对象,新增添加函数功能
创建function作为一个类,并向其添加两个方法(这里是链式添加)
使用new关键字创建对象实例,调用方法

三,结尾

简单的一个校验方法可以有如此多的实现方式,可以看出JS是相当灵活的一门语言
在JS的世界里,函数是"一等公民"

为了给JS设计模式打好基础,还要再看一下JS面向对象的编程方式 

你可能感兴趣的:(JavaScript,JavaScript设计模式)