prototype.js 源码之扩展Object
Object是其他对象实例的构造函数(var a=new Object()),也是所有其他类的父类,对Object直接扩展(注意不是扩展Object.prototype,扩展 Object.prototype相当于添加实例方法)相当于为Object类添加静态方法。
在对Object的扩展代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | (function() {
//Object对象的toString方法的引用
var _toString = Object.prototype.toString;
//属性拷贝
function extend(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}
//调用object的inspect(如果定义了)或toString方法,返回一个对象的字符串表示
function inspect(object) {
try {
if (isUndefined(object)) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
}
function toJSON(object) {
var type = typeof object;
switch (type) {
case 'undefined':
case 'function':
case 'unknown': return;
case 'boolean': return object.toString();
}
if (object === null) return 'null';
if (object.toJSON) return object.toJSON();
if (isElement(object)) return;
var results = [];
//递归调用
for (var property in object) {
var value = toJSON(object[property]);
if (!isUndefined(value))
results.push(property.toJSON() + ': ' + value);
}
return '{' + results.join(', ') + '}';
}
//将一个对象转化为hash码
function toQueryString(object) {
return $H(object).toQueryString();
}
function toHTML(object) {
return object && object.toHTML ? object.toHTML() : String.interpret(object);
}
//得到一个对象的所有属性名称
function keys(object) {
var results = [];
for (var property in object)
results.push(property);
return results;
}
//得到一个对象的所有属性值
function values(object) {
var results = [];
for (var property in object)
results.push(object[property]);
return results;
}
//克隆一个对象,返回新的对象
function clone(object) {
return extend({ }, object);
}
//判断一个对象是否是Element
function isElement(object) {
return !!(object && object.nodeType == 1);
}
//判断一个对象是否是数组
function isArray(object) {
return _toString.call(object) == "[object Array]";
}
//判断一个对象是否是Hash
function isHash(object) {
return object instanceof Hash;
}
function isFunction(object) {
return typeof object === "function";
}
function isString(object) {
return _toString.call(object) == "[object String]";
}
function isNumber(object) {
return _toString.call(object) == "[object Number]";
}
function isUndefined(object) {
return typeof object === "undefined";
}
extend(Object, {
extend: extend,
inspect: inspect,
toJSON: toJSON,
toQueryString: toQueryString,
toHTML: toHTML,
keys: keys,
values: values,
clone: clone,
isElement: isElement,
isArray: isArray,
isHash: isHash,
isFunction: isFunction,
isString: isString,
isNumber: isNumber,
isUndefined: isUndefined
});
})(); |
给一个对象增加一些属性和方法可以在其原型上增加,但是Prototype却并没有这么做,而是采用了现在广为流行的extend继承方式,jQuery和ExtJs也都采用了这种方式。
在上面代码中,定义了一个闭包,闭包内包括一些函数,为了将这些函数或是成为方法赋给Object对象,Prototype采用了extend机制。所谓extend,无外乎就是讲一个对象的属性和方法拷贝到另一个对象上去,这样另一个对象也就有了相同的属性和方法。
上面的代码中有对javascript各种对象类型的判断,其判断方式值得学习。
判断一个对象是否是函数,用typeof object === “function”,为什么不用“==”?因为“===”是全等运算符,其比较的是两个对象的值和类型,只有当两个对象的值和类型都相同时才是相等。需要注意到,在判断一个对象是否undefined时候,也是用到了“===”,如:typeof object === “undefined”
判断一个对象是字符串或是数字或是数组,采用了Object.prototype.toString.call()的方法,直接判断一个对象的字符串形式是否和目标对象(字符串或是数字或是数组)的字符串形式是否相同。
在闭包定义一些方法,然后在用extend方法将这些方法拷贝到Object对象,这样的话Object对象里就有了一些我们想要的方法了,这有点类似AOP的思想,往一个对象里注入我们想要的属性或方法。
看了上面的代码,让我想起来之前看到的一些类似的代码,下面这段代码来自于ExtJs的Ext.js文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | isArray: function(v){
return Object.prototype.toString.apply(v) === '[object Array]';
},
isObject: function(v){
return v && typeof v == "object";
},
isPrimitive: function(v){
var t = typeof v;
return t == 'string' || t == 'number' || t == 'boolean';
},
isFunction: function(v){
return typeof v == "function";
}, |
Recent Comments