prototype.js 源码之扩展Object

添加评论 27 views 2010年9月7日

Object是其他对象实例的构造函数(var a=new Object()),也是所有其他类的父类,对Object直接扩展(注意不是扩展Object.prototype,扩展 Object.prototype相当于添加实例方法)相当于为Object类添加静态方法。

在对Object的扩展代码如下:

?View Code JAVASCRIPT
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文件。

?View Code JAVASCRIPT
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";
        },
  1. 还没有评论.想坐沙发?
  1. 还没有 trackbacks
订阅评论