本文总结于《JavaScript 设计模式》(作者是张容铭)这本书第一章,主要讨论JS的几种函数编写方式。
- 最基础方法:下面两种方法基本等价,区别是前者的函数名在 function 之后,而后者需要提前声明。
function checkName() {}
function checkEmail() {}
function checkPassword() {}
var checkName = function () {}
var checkEmail = function () {}
var checkPassword = function () {}
优点:简单方便。
缺点:都创建了不少全局变量,方法之间易被相互覆盖。
那么将这些方法放在一个变量里保存,是不是就能减少覆盖几率了?
- 用对象收编变量:访问对象的属性和方法时可通过点语法向下遍历得到,所以可以创建一个检测对象,把方法放在里面。
var CheckObject = {
checkName : function () {},
checkEmail : function () {},
checkPassword : function () {}
}
var CheckObject = function () {};
CheckObject.checkName = function () {}
CheckObject.checkEmail = function () {}
CheckObject.checkPassword = function () {}
优点:减少覆盖和被覆盖的风险。
缺点:这个对象类在使用 new 关键字创建新的对象时,新创建的对象不能继承这些方法。
- 简单复制对象:将方法放在一个函数对象中,每次调用这个函数的时候,把这个对象返回。
var CheckObject = function () {
return {
checkName : function () {},
checkEmail : function () {},
checkPassword : function () {}
}
}
// 调用
var a = CheckObject();
a.checkEmail();
优点:每次调用这个函数的时候都返回一个新对象,每个人使用的时候互不影响。
缺点:不是一个真正意义上类的创建方式,且创建的对象 a 与对象 CheckObject 无关系。
- 继续改造:将方法放在函数内部,通过 this 定义。
var CheckObject = function () {
this.checkName = function () {}
this.checkEmail = function () {}
this.checkPassword = function () {}
}
// 调用
var a = new CheckObject(); //注意这个new
a.checkEmail();
优点:每次通过 new 创建新对象时,新对象都会复制类的 this 上的属性,新对象都有自己的一套方法。
缺点:因为是类,所以需要用 new 关键字来创建对象。有时候会很消耗资源。
- 节省资源:依赖 prototype 原型依次寻找方法,找到都是绑定在 Object 对象类原型上的同一个方法。
var CheckObject = function () {};
CheckObject.prototype.checkName = function () {}
CheckObject.prototype.checkEmail = function () {}
CheckObject.prototype.checkPassword = function () {}
优点:创建对象实例时,新对象拥有的方法都是一个。
缺点:prototype 需要写很多遍。
那么可以这么改:但这两种方式不可混用,否则后面为对象的原型对象赋值新对象时,会覆盖掉之前对 prototype 对象赋值的方法。
var CheckObject = function () {};
CheckObject.prototype = {
checkName : function () {},
checkEmail : function () {},
checkPassword : function () {}
}
// 调用
var a = new CheckObject();
a.checkName();
a.checkEmail();
a.checkPassword();
在调用的时候 a 对象书写了多遍,还可以加强功能吗?
- 加强功能:在声明的每一个方法末尾将当前对象返回。JS 中的 this 指向的就是当前对象。
var CheckObject = {
checkName : function () { return this; },
checkEmail : function () { return this; },
checkPassword : function () { return this; }
}// 调用
CheckObject.checkName().checkEmail().checkPassword();
var CheckObject = function () {}
CheckObject.prototype = {
checkName : function () { return this; },
checkEmail : function () { return this; },
checkPassword : function () { return this; }
}// 调用,使用之前需要创建一下。var a =new CheckObject();
a.checkName().checkEmail().checkPassword();
- 介绍 prototype.js 框架 :最大特点是对原生对象(JS 为我们提供的对象类,如 Function、Array、Object…)的拓展,比如想给每一个函数添加一个检测邮箱的方法:
Function.prototype.checkEmail = function () {}
//函数形式调用
var f = function(){};
f.checkEmail();
//类的形式调用
var f = new Function();
f.checkEmail();
但是这种方法污染了原生对象,别人创建的函数也会被你创建的函数污染。如何解决这个办法?
抽象出一个统一添加方法的功能方法:
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 = function(){};
methods.addMethod('checkName', function(){
return this;
}).addMethod('checkEmail', function(){
return this;
});
//调用methods.checkName().checkEmail();
//类式
Function.prototype.addMethod = function (name, fn) {
this.prototype[name] = fn;
}
var Methods = function(){};
Methods.addMethod('checkName', function(){
return this;
}).addMethod('checkEmail', function(){
return this;
});
//调用
var m = new Methods();
m.checkEmail();
最后,这本书跟《大话数据结构》的叙述方式都属于风趣类型,一下就吸引了我的注意力…今天读了前两章,收获颇深。觉得必须将知识点总结下来,加强记忆和便于复习。