1.javascript中定义类的步骤可以概括为一个分三步的算法,第一步,先定义一个
构造函数,并设置初始化新对象的实例属性。第二步,给构造函数的prototype对象
定义实例方法。第三步,给构造函数定义类属性和类方法,我们可以将这三个步骤
封装进一个简单的defineClass函数中:
//一个用以定义简单类的函数
function defineClass(constructor,methods,statics) {
if(methods)extend(constructor.prototype,methods);
if(statics) extend(constructor,statics);
return constructor;
}
2.extend函数
//定义一个扩展函数,用来将第二及后续参数复制到第一个参数
//这里我们处理了IE BUG:在多数IE版本中//如果o的属性拥有一个不可枚举的同名属性,则for/in循环
//不会枚举对象o的可枚举属性,也就是说,将不会正确处理诸如toString的属性
//除非我们显示检测它
var extend = (function() {
//在修复之前,首先检查是否存在BUG
for(var p in {toString : null}) {
//如果代码执行到这里,那么for/in循环会正确工作并返回
//一个简单版本的extend函数
return function extend(o) {
for(var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for(var prop in source) o[p] = source[p];
}
return o;
}
}
//如果代码执行到这里,说明for/in循环不会枚举测试对象的toString属性
//因此返回另一个版本的extend函数,这个函数显示测试
//Object.prototype中的不可枚举属性
return function patched_extend(o) {
for(var i = 1; i < arguments.length; i++) {
var source = arguments[i];
//复制所有的可枚举属性
for(var prop in source) o[prop] = source[prop];
//现在检查特殊属性
for(var j = 0; j < protoprops.length; j++) {
prop = protoprops[j];
if(source.hasOwnProperty(prop))o[prop] = source[prop];
}
}
return o;
};
//这个列表列出了需要检查的特殊属性
var protoprops = ["toString","valueOf","constructor","hasOwnProperty",
"isPrototypeOf","propertyIsEnumerable","toLocaleString"];
}());
3.FUNCTION加上GETNAME函数
Function.prototype.getName = function() {
if("name" in this) return this.name;
return this.name = this.toString().match(/function\s*([^(]*)\(/)[1];
}
4.判断类型
//以字符串形式返回o的类型:
//如果o是null返回'null',如果o是NaN,返回‘nan'
//如果typeof返回的不是object,则返回这个值
//(注意,有些javascript的实现将正则表达式识别为函数)
//如果o的类不是‘Object‘,则返回这个值
//如果o包含构造函数并且这个构造函数具有名称,则返回这个名称
//否则,一律返回'Object'
function type(o) {
var t,c,n;//type,class,name
if(o === null) return 'null';
if(o !== o) return 'nan';
if((t = typeof o) != 'object') return t;
if((c = classof(o) != 'Object') return c;
if(o.constructor && typeof o.constructor === 'function'
&& (n = o.constructor.getName())) return n;
return 'Object';
}
返回对象的类
//可以判断值的类型的type函数
//返回对象的类
function classof(o) {
return Object.prototype.toString.call(o).slice(8,-1);
}