javascriptコンポーネント開発の基質継承実現
17343 ワード
前の記事では、Javascriptコンポーネントの開発方法について概ね紹介しましたが、この記事は主に基質の作成を覚えています.この基質は主に継承機能を実現しています.
なぜ基本クラスをカプセル化しますか?
この再構成プロジェクトは様々なコンポーネントを実装する必要があります.これらのコンポーネントの実現方法はほぼ同じです.管理を容易にするために、コードをできるだけ統一するために、コンポーネントにbaseベースをパッケージ化します.素晴らしいと書いています.私が書き換えたのはジョン・Reigによるこの実現方法です.
基本的なパッケージ方式と継承にはどのような方法がありますか?
これは各ライブラリのソースコードに対応しています.例えば、jqの中に$exted()浅いコピーを実現して、和深のコピー、prototype.jsの中のObject.extedの実現、およびExt.extedなど、彼らの実現はそれぞれ違っています.ここで簡単にprototype.jsのexted実現案を見てみます.
第二の関数Object.prototype.extedは、プロトタイプオブジェクトのインスタンス化オブジェクトにexted関数を追加します.
その中の精華の語句Object.exted.aply(this、[this、object]);Objectオブジェクト中のextedを静的方法として呼び出します.
一つ目のパラメータthisは、呼び出し対象自体を指し、二つ目のパラメータは、一つの配列であり、呼び出し対象自体と伝達される対象パラメータobject(一般的には、以下の例がある)
例:
以下はjqの実現方式を見ます.
なぜ基本クラスをカプセル化しますか?
この再構成プロジェクトは様々なコンポーネントを実装する必要があります.これらのコンポーネントの実現方法はほぼ同じです.管理を容易にするために、コードをできるだけ統一するために、コンポーネントに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 })();