javascriptコンポーネント開発の基質継承実現

17343 ワード

前の記事では、Javascriptコンポーネントの開発方法について概ね紹介しましたが、この記事は主に基質の作成を覚えています.この基質は主に継承機能を実現しています.
なぜ基本クラスをカプセル化しますか?
この再構成プロジェクトは様々なコンポーネントを実装する必要があります.これらのコンポーネントの実現方法はほぼ同じです.管理を容易にするために、コードをできるだけ統一するために、コンポーネントにbaseベースをパッケージ化します.素晴らしいと書いています.私が書き換えたのはジョン・Reigによるこの実現方法です.
基本的なパッケージ方式と継承にはどのような方法がありますか?
これは各ライブラリのソースコードに対応しています.例えば、jqの中に$exted()浅いコピーを実現して、和深のコピー、prototype.jsの中のObject.extedの実現、およびExt.extedなど、彼らの実現はそれぞれ違っています.ここで簡単にprototype.jsのexted実現案を見てみます.
 1 //Prptotype  extend, Object       ,
 2 Object.extend=function(destination,source) {
 3     for(property in source) {
 4         destination[property]=source[property];
 5     }
 6     return destination;
 7 }
 8 //  Object ,     ,    
 9 Object.prototype.extend = function(object) {
10   return Object.extend.apply(this, [this, object]);
11 }
最初の関数Object.extedは、オブジェクトコピーとして簡単に理解できます.オブジェクトはソースオブジェクトの属性と方法のすべてを持っています.
第二の関数Object.prototype.extedは、プロトタイプオブジェクトのインスタンス化オブジェクトにexted関数を追加します.
その中の精華の語句Object.exted.aply(this、[this、object]);Objectオブジェクト中のextedを静的方法として呼び出します.
一つ目のパラメータthisは、呼び出し対象自体を指し、二つ目のパラメータは、一つの配列であり、呼び出し対象自体と伝達される対象パラメータobject(一般的には、以下の例がある)
例:
 1 //    father
 2 function father(){}
 3 father.prototype={
 4     //    
 5 }
 6 //    son
 7 function son(){}
 8 son.prototype=(new father()).extend({
 9     //     
10     ....
11 })
上記の方法はObjectオブジェクトの属性を汚染するなどの良くないところがあります.複数のオブジェクトを拡張できません.
以下はjqの実現方式を見ます.
 1 jQuery.extend = jQuery.fn.extend = function() {
 2     var options, name, src, copy, copyIsArray, clone,
 3         target = arguments[0] || {},
 4         i = 1,
 5         length = arguments.length,
 6         deep = false;
 7 
 8     // Handle a deep copy situation        
 9     if ( typeof target === "boolean" ) {
10         deep = target;
11         target = arguments[1] || {};
12         // skip the boolean and the target     boolean       (   )
13         i = 2;
14     }
15 
16     // Handle case when target is a string or something (possible in deep copy)      (   )  Object  function   
17     if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
18         target = {};
19     }
20 
21     // extend jQuery itself if only one argument is passed        (   ) boolean     
22     if ( length === i ) {
23         target = this;
24         --i;
25     }
26 
27     for ( ; i < length; i++ ) {
28         // Only deal with non-null/undefined values        undefined  
29         if ( (options = arguments[ i ]) != null ) {
30             // Extend the base object        
31             for ( name in options ) {
32                 src = target[ name ];
33                 copy = options[ name ];
34 
35                 // Prevent never-ending loop      map     key value       
36                 if ( target === copy ) {
37                     continue;
38                 }
39 
40                 // Recurse if we're merging plain objects or arrays   copy               
41                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
42                     if ( copyIsArray ) {
43                         copyIsArray = false;
44                         clone = src && jQuery.isArray(src) ? src : [];
45 
46                     } else {
47                         clone = src && jQuery.isPlainObject(src) ? src : {};
48                     }
49 
50                     // Never move original objects, clone them
51                     target[ name ] = jQuery.extend( deep, clone, copy );
52 
53                 // Don't bring in undefined values  value          
54                 } else if ( copy !== undefined ) {
55                     target[ name ] = copy;
56                 }
57             }
58         }
59     }
60 
61     // Return the modified object
62     return target;
63 };
jqの実現はprototypeの実現の欠点を避けましたが、私達のコンポーネント開発ではjqに依存することはできませんので、以下のJohn Resiggの実現方式によって次のクラスのスーパーファーザーがあります.具体的にはコメントを見てください.
 1 //javascript         
 2 var Class = (function() {
 3   //  extend    
 4   var _extend = function() {
 5     //      ,         ,          
 6     var _mixProto = function(base, extend) {
 7       for (var key in extend) {
 8         if (extend.hasOwnProperty(key)) {
 9           base[key] = extend[key];
10         }
11       }
12     };
13     //       ,                   init    ,        
14     //       ,           init        ,                   
15     this.initializing = true;
16     //    
17     var prototype = new this();
18     //    
19     this.initializing = false;
20     //for           ,  Base.extend(events,addLog)
21     for (var i = 0,len = arguments.length; i < len; i++) {
22       //               
23       _mixProto(prototype, arguments[i].prototype||arguments[i]);
24     }
25 
26     /*        
27     var items = [].slice.call(arguments) || [];
28     var item;
29     //        ,    {}    Function
30     while (item = items.shift()) {
31       _mixProto(prototype, item.prototype || item);
32     }
33     */
34 
35     //        
36     function SonClass() {
37       //     init     ,        
38       if (!SonClass.initializing && this.init)
39         //           ,--          ,              ,            。  JavaScript ,                   ,     this     。           ,           ,      。         (  )            init    ,            init  ,   apply           this  
40         this.init.apply(this, arguments);
41     }
42     //                    
43     SonClass.prototype = prototype;
44     //  constructor  ,             Class    
45     SonClass.prototype.constructor = SonClass;
46     //           ,         
47     SonClass.extend = arguments.callee;//    _extend
48     //    
49     return SonClass
50   };
51   //    
52   var Class = function() {};
53   
54   Class.extend = _extend;
55   //      
56   return Class
57   
58 })();
John Resig類の実装を添付します.
 1 /* Simple JavaScript Inheritance
 2  * By John Resig http://ejohn.org/
 3  * MIT Licensed.
 4  */
 5 // Inspired by base2 and Prototype
 6 (function(){
 7   //initializing                         。                   。              。               init    ,  initializing                , true       init。
 8   //fnTest             super   。       `function(){xyz;}`       ,            ,        。`/xyz/.test(function(){xyz;})` true                ,   `/\b_super\b/`   。    ,        。        super   ,            。
 9   var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
10  
11   // The base Class implementation (does nothing)
12   //     
13   this.Class = function(){};
14  
15   // Create a new Class that inherits from this class
16   //      ,      extend          
17   Class.extend = function(prop) {
18     //
19     //this    。     Class    
20     var _super = this.prototype;
21    
22     // Instantiate a base class (but only create the instance,
23     // don't run the init constructor)
24     //                     
25     initializing = true;
26     var prototype = new this();
27     initializing = false;
28    
29     // Copy the properties over onto the new prototype
30     for (var name in prop) {
31       // Check if we're overwriting an existing function
32       //           prop            。                
33       prototype[name] = typeof prop[name] == "function" &&
34         typeof _super[name] == "function" && fnTest.test(prop[name]) ?
35         (function(name, fn){
36           //    ,          .      ,             
37           return function() {
38             var tmp = this._super;
39            
40             // Add a new ._super() method that is the same method
41             // but on the super-class
42             //        ,  this    _super             
43             this._super = _super[name];
44            
45             // The method only need to be bound temporarily, so we
46             // remove it when we're done executing
47             //       ,     fn      _super         
48             var ret = fn.apply(this, arguments);  
49             //          ,   。
50             this._super = tmp;
51            
52             return ret;
53           };
54         })(name, prop[name]) :
55         prop[name];
56     }
57    
58     //
59     function Class() {
60       // All construction is actually done in the init method
61       if ( !initializing && this.init )
62         this.init.apply(this, arguments);
63     }
64    
65     //
66     Class.prototype = prototype;
67    
68     //   constructor  
69     Class.prototype.constructor = Class;
70  
71     //       extend  
72     Class.extend = arguments.callee;
73    
74     return Class;
75   };
76 })();