1 var Namespace = (function(){
2 /* ユーティリティ */
3 var merge = function(target, source){ // ソースのすべてのプロパティをターゲットにコピーします Go とreturn ターゲット オブジェクト 4 for(var p in source)
5 if(source.hasOwnProperty( p )) target[p] = source[p]
7 }; 8 var _assertValidFQN = function(fqn){ // 名前空間名の有効性を検証します。名前空間名は小文字の英数字、アンダースコア、ドット
9 である必要があります if(!(/^[a-z0-9_.] /) .test (fqn)) throw('無効な名前空間');
11
12 var Procedure = function _Private_Class_Of_Proc(){
13 merge(this, {
14 状態 : { }, // ステータス
15 ステップ : [], // ステータスを格納する配列
16 _status: 'init'
17 });
18 }); prototype, {
20 next: function(state){ // state に値がある場合、それをステップ キューの最後に格納し、この
21 if(state) this.enqueue(state) を返します。 ;
22 return this;
23 },
24 isRunning: function(){ // 実行中かどうかを判断します status
25 return (this._status === 'running'); 🎜>26 },
27 enqueue: function(state){ // ここでは、実際に配列のステップを使用してキューをシミュレートし、enqueue をキューの最後からキューに入れます
28 this。 step.push(state);
29 } ,
30 dequeue: function(){ // デキューとは、反対側からのデキューを意味します
31 return this.steps.shift(); ,
33 call: function(initialState,callback) { //
34 if( this.isRunning() ) throw("2 回実行しないでください");
35
36 this.state = InitialState || {}; // 現在の状態を保存します (NamespaceDefinition オブジェクト)
37 this.enqueue(function($c){ // 関数はキューに登録されています
38 $c(); // 関数を実行しますpass in
39 if(callback)callback(this) ; // コールバック関数がある場合は、コールバック関数を実行します。
40 });
41 this._status = 'running';実行中のステータス
42 this._invoke(); // _invoke を呼び出します
43 },
44 _invoke: function(){
45 var _self = this; _self.dequeue(); // オブジェクトのデキュー (FIFO)
47 if( !step ){
48 _self._status = 'finished' // キューが空の場合、ステータスを終了に設定します
49 return;
50 } // step が配列の場合はこのパスをたどらないでください
51 if( step.call ) { // オブジェクトが関数オブジェクトの場合、call メソッドを実行し、指定します内部の this を _self.state として扱い、コールバック関数で呼び出しを継続します。
52 return step.call( _self.state,function _cont(state){
53 if( state ) _self.state = state;
54 _self._invoke();
55 }) ;
56 }
57 var completedProcess = 0;
58 if( step.length === 0 ) _self._invoke(); // 配列の長さが 0 の場合、_invoke
59 for(var i =0,l=step.length;i63 _invoke();
64 }
65 }); 69
70 var createProcedure = function(state) {
71 return new Procedure().next(state)
72 };
73
74 var NamespaceObject = function _Private_Class_Of_NamespaceObject(fqn) {
75 merge(this, {
76 stash: { CURRENT_NAMESPACE : fqn },
77 fqn : fqn,
78 proc : createProcedure()
79 }); };
81 merge(NamespaceObject.prototype, {
82 enqueue: function(context) {
83 this.proc.next(context);
84 },
85 call: function (state,callback) {
86 this.proc.call(state, callback);
88 valueOf: function() {
89 return "#NamespaceObject90 },
91 マージ: function(obj) {
92 merge(this.stash,obj);
94 },
95 getStash: function() {
96 return this .stash;
97 },
98 getExport: function(importName) {
99 if (importName === '*') return this .stash;
100
101 var importNames = importName.split(/,/),
102 retStash = {}
103 for(var i = 0,l=importNames.length;i< ;l;i ){
104 retStash[ importNames[i] ] = this.stash[ importNames[i] ];
106 return
107 }
108 } );
109 var NamespaceObjectFactory = (function() {
110 var queue = {};
111 return {
112 create :function(fqn){
113 _assertValidFQN(fqn);
114 return (cache[fqn] || (cache [fqn] = new NamespaceObject(fqn)));
115 }
117 })();
119 var NamespaceDefinition = function _Private_Class_Of_NamespaceDefinition(nsObj) {
120 merge(this, {
121 namespaceObject: nsObj,
122 Required : [],
123 useList : [],
124 スタッシュ : {},
125 定義コールバック : 未定義
126 });
127 var _self = this; nsObj.enqueue(function($c){ _self.apply($c) ); });;
130 merge(NamespaceDefinition.prototype, {
131 use: function(syntax){ // 名前空間を使用します
132 this.useList.push(syntax); // 名前空間文字列は配列に格納されますuseList
133 var splitted = syntax.split(/s /); // 名前空間とそのオブジェクトはスペースで区切られます
134 var fqn = splitted[0] // 名前空間を取得します
135 var importName = splitted [1]; // 名前空間内のオブジェクトを取得します
136 _assertValidFQN(fqn);
137 this.requires.push(function($c){ // 関数を require 配列に入れます
138 var context = this;
139 var require = NamespaceObjectFactory.create(fqn); // 指定された NamespaceObject オブジェクトをキャッシュから直接取得できます。
140 require.call(this,function(state) ){ // NamespaceObject オブジェクトの呼び出しメソッドを呼び出します。
141 context.loadImport(require,importName)
143 }); >145 これを返します;
146 },
147 _mergeStashWithNS: function(nsObj){
148 var nsList = nsObj.fqn.split(/./);
149 var current = this.getStash () ;
150
151 for(var i = 0,l=nsList.length;i152 if( !current[nsList[i]] ) current[ nsList[i]] = {};
153 current = current[nsList[i]]
155
156 var lastLeaf = nsList.length-1; >157 current[lastLeaf] = merge(current[lastLeaf] || {}, nsObj.getStash());
158 },
159 loadImport: function(nsObj,importName){
160 if( importName ) {
161 merge( this.stash, nsObj.getExport(importName) );
162 }else{
163 this._mergeStashWithNS( nsObj );
166 define: function(callback){
167 var nsDef = this, nsObj = this.namespaceObject;
168 this.defineCallback = function($c) { //defineCallback に値を代入し、コールバック関数コンテキスト、2 つのオブジェクト、nsDef と nsObj。
169 var ns = {
170 提供: function(obj){
171 nsObj.merge(obj);
172 $c() }
174 };
175 マージ(ns, nsDef.getStash());
177 コールバック(ns);
179 } ,
180 getStash: function(){
181 return this.stash;
182 },
183 valueOf: function(){
184 return "#NamespaceDefinition<" > を使用します:" this.useList.join(',');
185 },
186 apply: function(callback){
187 var nsDef = this;
188 createProcedure(nsDef.必要)
189 .next(nsDef.defineCallback)
190 .call(nsDef,function(){
191 callback( nsDef.getStash() );
192 }); }
194 });
195
196 var createNamespace = function(fqn){
197 return new NamespaceDefinition(
198 NamespaceObjectFactory.create(fqn || 'main')
199 );
200 };
201 merge(createNamespace, {
202 'オブジェクト' : NamespaceObjectFactory,
203 定義: NamespaceDefinition,
204 Proc : createProcedure
205 });
206 return createNamespace;
207 })();
Namespace でサポートされるメソッドを追加で定義します:
Namespace.use
Namespace.fromInternal
Namespace。 GET
Namespace.fromExternal
コードをコピー
コードは次のとおりです:
1 Namespace.use = function(useSyntax){ return Namespace().use(useSyntax); }
2 Namespace.fromInternal = Namespace.GET = (function(){
3 var get = (function(){
4 var createRequester = function() {
5 var xhr;
6 try { xhr = new XMLHttpRequest() } catch(e) {
7 try { xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0") } catch(e) {
8 try { xhr = new ActiveXObject("Msxml2.XMLHTTP.3.0") } catch(e) {
9 try { xhr = new ActiveXObject("Msxml2.XMLHTTP") } catch(e) {
10 try { xhr = new ActiveXObject( "Microsoft.XMLHTTP") } catch(e) {
11 throw new Error( "このブラウザは XMLHttpRequest をサポートしていません。" )
12 }
13 }
14 }
15 }
16 }
17 return xhr;
18 };
19 var isSuccessStatus = function(status) {
20 return (ステータス >= 200 && ステータス 21 ステータス == 304 ||
22 ステータス == 1223 ||
23 (!ステータス && (location.protocol == "file:" || location.protocol == "chrome:") ) ;
24 };
25
26 return function(url,callback){
27 var xhr = createRequester();
28 xhr.open('GET',url,true) ;
29 xhr.onreadystatechange = function(){
30 if(xhr.readyState === 4){
31 if( isSuccessStatus( xhr.status || 0 )){
32 callback(true,xhr.responseText);
33 }else{
34 コールバック(false);
35 }
36 }
37 };
38 xhr.send('')
39 };
40 })();
41
42 return function(url,isManualProvide){
43 return function(ns){
44 get(url,function(isSuccess,responseText){
45 if( isSuccess ){
46 if( isManualProvide )
47 return eval(responseText);
48 else
49 return ns.provide( eval(responseText ) ); pub = {};
52 pub[url] = '読み込みエラー'
53 ns.provide(pub);
56 };
57 };
58 })();
59
60 Namespace.fromExternal = (function(){
61 var callbacks = {};
62 var createScriptElement = function(url,callback){
63 var scriptElement = document. createElement('script');
64
65 scriptElement.loaded = false;
66
67 scriptElement.onload = function(){
68 this.loaded = true; 69 callback();
70 };
71 scriptElement.onreadystatechange = function(){
72 if( !/^(loaded|complete)$/.test( this.readyState )) return; 🎜>73 if( this.loaded ) return;
74 scriptElement.loaded = true;
77 scriptElement.src = url; .body.appendChild( scriptElement );
79 return scriptElement.src;
81 var domSrc = function(url){
83 var src = createScriptElement(url,function(){
84 var name = ns.CURRENT_NAMESPACE;
85 var cb = callbacks[name];
86 delete callbacks[name];
87 cb( ns );
88 });
89 }
90 };
91 domSrc.registerCallback = function(namespace,callback) {
92 callbacks[namespace] = コールバック;
93 };
94 domSrc を返します。
95 })();
96
97 try{ module.exports = 名前空間; }catch(e){}
具体的な例:
复制代幣
代価次のように:
1 名前空間('logtest')
2 .define(function (ns) {
3 console.log(2); 12 .use('logtest') 13 .apply( function (ns) {
14 console.log(5);
15 ns.logtest .log();
16 });
1:名前空間('logtest') => new NamespaceDefinition(NamespaceObjectFactory.create('logtest'))
つまり、1 つの NamespaceDefinition オブジェクトを生成します。このオブジェクトは、NamespaceObject オブジェクトによって初期化され、同時に 3 つのプロパティ、Object、Definition、Proc も持ちます。その値は、NamespaceObjectFactory に依存します。 ,NamespaceDefinition,createProcedure 関数オブジェクト クラス。Namespace('logtest') が返される結果は生成された NamespaceDefinition オブジェクトであり、その後、その define メソッドを使用して defineCallback が初期化されます。このときのみ、不特定の動作が行われます。
复制代码
代码如下:
166 定義: function(callback){
167 var nsDef = this、nsObj = this.namespaceObject;
168 this.defineCallback = function($c) { //defineCallback 値を定義し、同時に次の回帰関数の上下文、nsDef と nsObj の 2 つのオブジェクトを定義します。
169 var ns = {
170 は次を提供します: function(obj){
171 nsObj.merge(obj); 179 }、
2: 以前に定義した名前空間、Namespace.use() => Namespace().use() => Namespace('main').use() 内のオブジェクトを使用します。 use を呼び出すときに要件配列を初期化します。
131 use: function(syntax ){ // 名前空間を使用します
132 this.useList.push(syntax); // 名前空間文字列は配列 useList
133 に格納されます var splitted = syntax.split(/s /);そのオブジェクトはスペースで区切って使用されます
134 var fqn = splitted[0]; // 名前空間を取得します
135 var importName = splitted[1]; // 名前空間内のオブジェクトを取得します
136 _assertValidFQN(fqn);
137 this.requires.push(function($c){ // 関数を require 配列に入れます
138 var context = this;
139 var require = NamespaceObjectFactory.create(fqn); //指定された NamespaceObject オブジェクトを取得します。以前に生成されたオブジェクトはキャッシュから直接取得できます
140 require.call(this,function(state){ // NamespaceObject オブジェクトの call メソッドを呼び出します
141 context.loadImport(require ,importName);
142 $c();
144 });
146 },
3 : main の apply メソッドを呼び出します。具体的な適用メソッドを見てみましょう
187 var nsDef = this;
188 createProcedure(nsDef.requires)
189 .next(nsDef.defineCallback)
190 .call(nsDef,function() {
191 callback ( nsDef.getStash() );
192 });
requires 配列内のオブジェクトを取り出して Proc オブジェクトを生成します。 require 配列内のオブジェクトをキューに入れる step 、 nsDef.defineCallback もキューに登録され (この例では未定義)、Proc の call メソッドが呼び出されます。最初のパラメータは nsDef で、2 番目のパラメータはコールバック関数です。
具体的な使用法:
名前空間を定義するとき、すべての定義はdefineに配置され、匿名関数の形式で定義されます。 function (ns) { // 特定の実装 // 外部に公開されるオブジェクトを定義します。 nsName を使用した後、外部パーティは ns.nsName.key() ns.provide({ key : value} を介して呼び出すことができます)。 );}
namespace.js を使用する利点は、すべての定義が必要な場合にのみ実行されること、つまり、定義が実際に使用される場合にのみ解析されることです。
追伸: 具体的な内部呼び出し関係はまだ明確ではありません。今後時間があるときに整理します。