Github:https://github.com/hirokidaichi/namespace-js
Define namespace objects:
var Namespace
Now for a specific look at the definition of the Namespace object, it is a Namespacedefinition object. The object is a function object (the constructor of the Namespacedefinition object, which generates a main namespace by default if it is not given a parameter), and three properties, Object,definition,proc. The value is in turn the Namespaceobjectfactory,namespacedefinition,createprocedure function object class.
Copy Code code as follows:
196 var createnamespace = function (FQN) {
197 return New Namespacedefinition (
198 namespaceobjectfactory.create (FQN | | ' Main ')
199);
200};
201 Merge (Createnamespace, {
The ' Object ': namespaceobjectfactory,
203 Definition:namespacedefinition,
204 Proc:createprocedure
205});
Namespaceobjectfactory: Generates Namespaceobject objects based on FQN.
The Namespaceobjectfactory object has only one create method, and the parameter is the name of the namespace (fully qualified name). The method has a closure environment where a cache variable is used to cache all generated Namespaceobject objects.
A Namespaceobject object contains three attributes, stash (record current namespace), Fqn (namespace name), Proc (Createprocedure object). Methods include: Enqueue,call,valueof,merge,getstash,getexport
Copy Code code as follows:
Namespaceobject var = function _private_class_of_namespaceobject (FQN) {
Merge (this, {
Stash: {CURRENT_NAMESPACE:FQN},
FQN:FQN,
Proc:createprocedure ()
79});
80};
Bayi Merge (Namespaceobject.prototype, {
Enqueue:function (context) {
This.proc.next (context);
84},
Call:function (State,callback) {
This.proc.call (State, callback);
87},
Valueof:function () {
"#NamespaceObject <" + this.fqn + ">";
90},
Merge:function (obj) {
(This.stash,obj);
The return of this;
94},
Getstash:function () {
return this.stash;
97},
Getexport:function (ImportName) {
if (importname = = = ' * ') return this.stash;
100
The var importnames = Importname.split (/,/),
102 Retstash = {};
for (var i = 0,l=importnames.length;i<l;i++) {
retstash[Importnames[i]] = this.stash[Importnames[i]];
105}
The return retstash;
107}
108});
109 var namespaceobjectfactory = (function () {
The var cache = {};
I return {
112 Create:function (FQN) {
113 _ASSERTVALIDFQN (FQN);
114 return (CACHE[FQN] | | (CACHE[FQN] = new Namespaceobject (FQN)));
115}
116};
117}) ();
Namespacedefinition:
The object includes 5 properties, Namespaceobject,requires,uselist,stash,definecallback. and provides a related method: Use,_mergestashwithns,loadimport,define,getstash,valueof,apply
The object is the core of the namespace library, and it provides all the necessary methods.
When initialized, appends a function object to the steps queue of Namespaceobject's proc, which calls the Apply method.
Copy Code code as follows:
119 var namespacedefinition = function _private_class_of_namespacedefinition (nsobj) {
The merge (this, {
121 Namespaceobject:nsobj,
122 requires: [],
123 uselist: [],
124 stash: {},
definecallback:undefined
126});
127 var _self = this;
128 Nsobj.enqueue (function ($c) {_self.apply ($c);});
129};
130 merge (Namespacedefinition.prototype, {
131 use:function (Syntax) {
132 This.useList.push (syntax);
The splitted var = syntax.split (/\s+/);
134 var fqn = splitted[0];
135 var importname = splitted[1];
136 _ASSERTVALIDFQN (FQN);
137 This.requires.push (function ($c) {
138 var context = this;
139 var require = Namespaceobjectfactory.create (FQN);
140 Require.call (this,function (state) {
Context.loadimport (Require,importname);
$c ();
143});
144});
145 return to this;
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;i<l-1;i++) {
152 if (!current[nslist[i]]) current[nslist[i]] = {};
153 current = current[nslist[i]];
154}
155
156 var lastleaf = nslist[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);
164}
165},
166 Define:function (callback) {
167 var nsdef = this, nsobj = This.namespaceobject;
This.definecallback = function ($c) {
169 var ns = {
170 provide:function (obj) {
171 Nsobj.merge (obj);
172 $c ();
173}
174};
175 merge (NS, Nsdef.getstash ());
176 merge (NS, Nsobj.getstash ());
177 callback (NS);
178};
179},
180 getstash:function () {
181 return This.stash;
182},
183 Valueof:function () {
184 return "#NamespaceDefinition <" +this.namespaceobject+ "> Uses:" + this.useList.join (', ');
185},
186 Apply:function (callback) {
187 var nsdef = this;
188 Createprocedure (Nsdef.requires)
189. Next (Nsdef.definecallback)
190. Call (Nsdef,function () {
191 Callback (Nsdef.getstash ());
192});
193}
194});
Createprocedure: This object is a function object that returns the result of the next method of the procedure object.
Procedure:
The procedure object has three properties: State,steps,_status (Default is init). Provide several methods: Next,isrunnig,enqueue,dequeue,call,_invoke.
Copy Code code as follows:
1 var Namespace = (function () {
2/* Utility * *
3 var merge = function (target, source) {//Copy all of Source's own properties to target and return target object 4 for (Var p in Source)
5 if (Source.hasownproperty (p)) target[p] = source[p];
6 return target;
7};
8 var _assertvalidfqn = function (FQN) {//Verify validity of namespace name, must be lowercase English digit, underline and Dot
9 if (!) ( /^[a-z0-9_.] +/). Test (FQN)) throw (' Invalid namespace ');
10};
11
var Procedure = function _private_class_of_proc () {
Merge (this, {
State: {},//Status
Steps: [],//storing an array of states
_status: ' Init '
17});
18};
Merge (Procedure.prototype, {
Next:function (state) {//If State has a value, save to the end of the steps queue and return this
if (state) This.enqueue (state);
return to this;
23},
Isrunning:function () {//determine if running status
return (This._status = = ' running ');
26},
Enqueue:function (state) {//This is actually an array steps to simulate the queue, Enqueue is the queue from the end of the team
This.steps.push (state);
29},
Dequeue:function () {//dequeue is the right out of the queue
return This.steps.shift ();
32},
Call:function (Initialstate,callback) {//
if (this.isrunning ()) throw ("Do not run Twice");
35
This.state = Initialstate | | {}; Saves the current state (Namespacedefinition object)
Notoginseng this.enqueue (function ($c) {//functions into queue steps
$c (); Perform the passed in function
Callback callback (this); If there is a callback function, execute the callback function
40});
This._status = ' running '; Set status to Running
This._invoke (); Call _invoke
43},
_invoke:function () {
var _self = this;
The var step = _self.dequeue (); Object out Queue (FIFO)
if (!step) {
_self._status = ' finished '; If the queue is empty, the setting state is finished
return;
A//step is an array of cases not going this way
May if (Step.call) {//If the object is a function object, execute the call method and specify internal this as _self.state, and the callback function continues to invoke the _invoke
Step.call (_self.state,function _cont (state) {
_self.state = State;
_self._invoke ();
55});
56}
var finishedprocess = 0;
if (step.length = 0) _self._invoke (); If the array length is 0, then the _invoke is called
The (var i =0,l=step.length;i<l;i++) {//Call method is invoked for all objects (function objects) in the array, and specifies this as the _self.state object (Nsdef object) of the respective function.
Step[i].call (_self.state,function _joinwait () {
finishedprocess++;
if (finishedprocess = = L) {
_self._invoke ();
64}
65});
66}
67}
68});
69
$ var createprocedure = function (state) {
Return to New Procedure (). Next (state);
72};
73
Namespaceobject var = function _private_class_of_namespaceobject (FQN) {
Merge (this, {
Stash: {CURRENT_NAMESPACE:FQN},
FQN:FQN,
Proc:createprocedure ()
79});
80};
Bayi Merge (Namespaceobject.prototype, {
Enqueue:function (context) {
This.proc.next (context);
84},
Call:function (State,callback) {
This.proc.call (State, callback);
87},
Valueof:function () {
"#NamespaceObject <" + this.fqn + ">";
90},
Merge:function (obj) {
(This.stash,obj);
The return of this;
94},
Getstash:function () {
return this.stash;
97},
Getexport:function (ImportName) {
if (importname = = = ' * ') return this.stash;
100
The var importnames = Importname.split (/,/),
102 Retstash = {};
for (var i = 0,l=importnames.length;i<l;i++) {
retstash[Importnames[i]] = this.stash[Importnames[i]];
105}
The return retstash;
107}
108});
109 var namespaceobjectfactory = (function () {
The var cache = {};
I return {
112 Create:function (FQN) {
113 _ASSERTVALIDFQN (FQN);
114 return (CACHE[FQN] | | (CACHE[FQN] = new Namespaceobject (FQN)));
115}
116};
117}) ();
118
119 var namespacedefinition = function _private_class_of_namespacedefinition (nsobj) {
The merge (this, {
121 Namespaceobject:nsobj,
122 requires: [],
123 uselist: [],
124 stash: {},
definecallback:undefined
126});
127 var _self = this;
128 Nsobj.enqueue (function ($c) {_self.apply ($c);});
129};
130 merge (Namespacedefinition.prototype, {
131 use:function (Syntax) {//Use namespace
132 This.useList.push (syntax); The namespace string is stored in an array uselist
The splitted var = syntax.split (/\s+/); namespace and its objects are separated by spaces
134 var fqn = splitted[0]; Get namespace
135 var importname = splitted[1]; Get the object in namespace
136 _ASSERTVALIDFQN (FQN);
137 This.requires.push (function ($c) {//Put a functions into requires array
138 var context = this;
139 var require = Namespaceobjectfactory.create (FQN); Gets the specified Namespaceobject object from which the previously generated object can be retrieved directly from the cache
140 Require.call (this,function (state) {//Invoke call method for Namespaceobject object
Context.loadimport (Require,importname);
$c ();
143});
144});
145 return to this;
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;i<l-1;i++) {
152 if (!current[nslist[i]]) current[nslist[i]] = {};
153 current = current[nslist[i]];
154}
155
156 var lastleaf = nslist[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);
164}
165},
166 Define:function (callback) {
167 var nsdef = this, nsobj = This.namespaceobject;
This.definecallback = function ($c) {//Assign value to Definecallback, define the context of the callback function, Nsdef and nsobj two objects.
169 var ns = {
170 provide:function (obj) {
171 Nsobj.merge (obj);
172 $c ();
173}
174};
175 merge (NS, Nsdef.getstash ());
176 merge (NS, Nsobj.getstash ());
177 callback (NS);
178};
179},
180 getstash:function () {
181 return This.stash;
182},
183 Valueof:function () {
184 return "#NamespaceDefinition <" +this.namespaceobject+ "> Uses:" + this.useList.join (', ');
185},
186 Apply:function (callback) {
187 var nsdef = this;
188 Createprocedure (Nsdef.requires)
189. Next (Nsdef.definecallback)
190. Call (Nsdef,function () {
191 Callback (Nsdef.getstash ());
192});
193}
194});
09T
196 var createnamespace = function (FQN) {
197 return New Namespacedefinition (
198 namespaceobjectfactory.create (FQN | | ' Main ')
199);
200};
201 Merge (Createnamespace, {
The ' Object ': namespaceobjectfactory,
203 Definition:namespacedefinition,
204 Proc:createprocedure
205});
206 return createnamespace;
207}) ();
Append to define namespace support methods:
Namespace.use
Namespace.frominternal
Namespace.get
Namespace.fromexternal
Copy Code code as follows:
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) {
Ten try {xhr = new ActiveXObject ("Microsoft.XMLHTTP")} catch (e) {
One throw new Error ("This browser does is not support XMLHttpRequest.")
12}
13}
14}
15}
16}
return XHR;
18};
var issuccessstatus = function (status) {
Return (status >= && status < 300) | |
Status = = 304 | |
Status = 1223 | |
!status && (Location.protocol = = "File:" | | Location.protocol = = "Chrome:");
24};
25
The return function (Url,callback) {
var xhr = Createrequester ();
Xhr.open (' Get ', url,true);
Xhr.onreadystatechange = function () {
if (xhr.readystate = = 4) {
if (Issuccessstatus (Xhr.status | | 0)) {
Callback (True,xhr.responsetext);
}else{
Callback (FALSE);
35}
36}
37};
Xhr.send (')
39};
40}) ();
41
The return function (url,ismanualprovide) {
The return function (NS) {
Url,function (Issuccess,responsetext) {
if (issuccess) {
if (ismanualprovide)
Return eval (responsetext);
Or else
Return Ns.provide (eval (responsetext));
M}else{
Wuyi var pub = {};
Pub[url] = ' loading error ';
Ns.provide (pub);
54}
55});
56};
57};
58}) ();
59
Namespace.fromexternal = (function () {
The var callbacks = {};
The var createscriptelement = function (url,callback) {
The var scriptelement = document.createelement (' script ');
64
scriptelement.loaded = false;
66
Scriptelement.onload = function () {
This.loaded = true;
Callback ();
70};
Scriptelement.onreadystatechange = function () {
if (!/^ (loaded|complete) $/.test (this.readystate)) return;
if (this.loaded) return;
Scriptelement.loaded = true;
Callback ();
76};
scriptelement.src = URL;
Document.body.appendChild (scriptelement);
SCRIPTELEMENT.SRC return;
80};
Bayi var domsrc = function (URL) {
The The return function (NS) {
The var src = createscriptelement (url,function () {
The ' var ' name = ns. Current_namespace;
The var cb = Callbacks[name];
Delete Callbacks[name];
CB (NS);
88});
89}
90};
Domsrc.registercallback = function (namespace,callback) {
Callbacks[namespace] = callback;
93};
return DOMSRC;
95}) ();
96
try{module.exports = Namespace; catch (e) {}
Look at one example:
Copy Code code as follows:
1 Namespace (' logtest ')
2. Define (function (NS) {
3 Console.log (2);
4 Ns.provide ({
5 log:function () {console.log (3);}
6});
7});
8
9 Console.log (4);
10
One Namespace
Use (' Logtest ')
Apply (function (NS) {
Console.log (5);
Ns.logtest.log ();
16});
1:namespace (' logtest ') => new Namespacedefinition (namespaceobjectfactory.create (' logtest '))
A Namespacedefinition object is generated that is initialized by the Namespaceobject object, which also has three properties, Object,definition,proc. The value is in turn the Namespaceobjectfactory,namespacedefinition,createprocedure function object class. The result returned by Namespace (' Logtest ') is the generated Namespacedefinition object, and then calls its define method to initialize Definecallback. This is just a definition, not a specific action.
Copy Code code as follows:
166 Define:function (callback) {
167 var nsdef = this, nsobj = This.namespaceobject;
This.definecallback = function ($c) {//Assign value to Definecallback, define the context of the callback function, Nsdef and nsobj two objects.
169 var ns = {
170 provide:function (obj) {
171 Nsobj.merge (obj);
172 $c ();
173}
174};
175 merge (NS, Nsdef.getstash ());
176 merge (NS, Nsobj.getstash ());
177 callback (NS);
178};
179},
2: Use the object in the previously defined Namespace, Namespace.use () => Namespace (). using () => Namespace (' main '). Use (). Initializes the requires array when the use is invoked.
Copy Code code as follows:
131 use:function (Syntax) {//Use namespace
132 This.useList.push (syntax); The namespace string is stored in an array uselist
The splitted var = syntax.split (/\s+/); namespace and its objects are separated by spaces
134 var fqn = splitted[0]; Get namespace
135 var importname = splitted[1]; Get the object in namespace
136 _ASSERTVALIDFQN (FQN);
137 This.requires.push (function ($c) {//Put a functions into requires array
138 var context = this;
139 var require = Namespaceobjectfactory.create (FQN); Gets the specified Namespaceobject object from which the previously generated object can be retrieved directly from the cache
140 Require.call (this,function (state) {//Invoke call method for Namespaceobject object
Context.loadimport (Require,importname);
$c ();
143});
144});
145 return to this;
146},
3: Invoke the Apply method of main. Take a look at the specific apply method
Copy Code code as follows:
186 Apply:function (callback) {
187 var nsdef = this;
188 Createprocedure (Nsdef.requires)
189. Next (Nsdef.definecallback)
190. Call (Nsdef,function () {
191 Callback (Nsdef.getstash ());
192});
193}
The object in the requires array is taken out and the proc object is generated, the object in the requires array is entered into the queue steps, and the Nsdef.definecallback is also queued (in this case undefined), and the call method of Proc is invoked. The first argument is Nsdef, and the second parameter is the callback function.
The specific use method:
When defining namespace, all definitions are placed inside the define and are defined as anonymous functions. function (NS) {//a concrete implementation//definition of externally exposed objects that can be invoked by Ns.nsName.key () after the use of the Nsname ({key:value});}
With the benefits of namespace.js, all definitions begin when they are needed, that is, to begin parsing the definition when used specifically.
PS: The specific internal call relationship is still not clear, in the future, there is time to tidy, this article is too messy.