Home Web Front-end JS Tutorial namespace.js Javascript namespace library_javascript tips

namespace.js Javascript namespace library_javascript tips

May 16, 2016 pm 06:01 PM
Namespaces

github: https://github.com/hirokidaichi/namespace-js
Define the Namespace object:
var Namespace
Now let’s take a closer look at the definition of the Namespace object, which is a NamespaceDefinition object. This object is a function object (the constructor of the NamespaceDefinition object, if no parameters are given, a main namespace will be generated by default), and there are three attributes, Object, Definition, and Proc. Its values ​​are NamespaceObjectFactory, NamespaceDefinition, and createProcedure function object classes.

Copy code The code is as follows:

196 var createNamespace = function(fqn){
197 return new NamespaceDefinition(
198 NamespaceObjectFactory.create(fqn || 'main')
199 );
200 };
201 merge(createNamespace, {
202 'Object' : NamespaceObjectFactory ,
203 Definition: NamespaceDefinition,
204 Proc : createProcedure
205 });

NamespaceObjectFactory: Generate NamespaceObject object based on fqn.
The NamespaceObjectFactory object has only one create method, and the parameter is the name of the namespace (Fully Qualified Name). This method has a closure environment, which has a cache variable used to cache all generated NamespaceObject objects.
A NamespaceObject object contains three attributes, stash (record the current namespace), fqn (namespace name), proc (createProcedure object). Methods include: enqueue, call, valueof, merge, getStash, getExport
Copy code The code is as follows:

74 var NamespaceObject = function _Private_Class_Of_NamespaceObject(fqn){
75 merge(this, {
76 stash: { CURRENT_NAMESPACE : fqn },
77 fqn : fqn,
78 proc : createProcedure()
79 });
80 };
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);
87 },
88 valueOf: function() {
89 return "#NamespaceObject<" this.fqn ">";
90 },
91 merge: function(obj) {
92 merge(this.stash,obj);
93 return this;
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;i104 retStash[ importNames[i] ] = this.stash[ importNames[i] ];
105 }
106 return retStash ;
107 }
108 });
109 var NamespaceObjectFactory = (function() {
110 var cache = {};
111 return {
112 create :function(fqn ){
113 _assertValidFQN(fqn);
114 return (cache[fqn] || (cache[fqn] = new NamespaceObject(fqn)));
115 }
116 };
117 })();

NamespaceDefinition:
This object includes 5 properties, namespaceObject, requires, useList, stash, defineCallback. And provides related methods: use, _mergeStashWithNS, loadImport, define, getStash, valueOf, apply
This object is the core of the namespace library, which provides all required methods.
During initialization, add a function object to the steps queue of NamespaceObject's proc, and the function will call the apply method.
Copy code The code is as follows:

119 var NamespaceDefinition = function _Private_Class_Of_NamespaceDefinition(nsObj) {
120 merge(this, {
121 namespaceObject: nsObj,
122 requires : [],
123 useList : [],
124 stash : {},
125 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);
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){
138 var context = this;
139 var require = NamespaceObjectFactory.create(fqn);
140 require.call(this,function(state){
141 context.loadImport(require,importName);
142 $c();
143 });
144 });
145 return 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;i152 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;
168 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:该对象是一个函数对象,返回Procedure对象的next方法的结果。
Procedure:
Procedure对象有三个属性:state,steps,_status(默认为init)。提供一下几种方法:next,isRunnig,enqueue,dequeue,call,_invoke。

复制代码 代码如下:

1 var Namespace = (function(){
2 /* utility */
3 var merge = function(target, source){ // Copy all the properties of source to target Go 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 the validity of the namespace name, which must be lowercase alphanumeric, underscore and dot
9 if(!(/^[a-z0-9_.] /) .test(fqn)) throw('invalid namespace');
10 };
11
12 var Procedure = function _Private_Class_Of_Proc(){
13 merge(this, {
14 state : {}, // Status
15 steps : [], // Array to store status
16 _status: 'init'
17 });
18 };
19 merge( Procedure.prototype, {
20 next: function(state){ // If state has a value, store it at the end of the steps queue, and then return this
21 if(state) this.enqueue(state);
22 return this;
23 },
24 isRunning: function(){ // Determine whether it is running status
25 return (this._status === 'running');
26 },
27 enqueue: function(state){ // Here, the array steps is actually used to simulate the queue, and enqueue is put into the queue from the end of the queue
28 this.steps.push(state);
29 } ,
30 dequeue: function(){ // dequeue means dequeuing from the opposite end
31 return this.steps.shift();
32 },
33 call: function(initialState,callback) { //
34 if( this.isRunning() ) throw("do not run twice");
35
36 this.state = initialState || {}; // Save the current state (NamespaceDefinition Object)
37 this.enqueue(function($c){ // Function is queued steps
38 $c(); // Execute the function passed in
39 if(callback)callback(this) ; // If there is a callback function, execute the callback function
40 });
41 this._status = 'running'; // Set the status to running
42 this._invoke(); // Call _invoke
43 },
44 _invoke: function(){
45 var _self = this;
46 var step = _self.dequeue(); // Object dequeue (FIFO)
47 if( !step ){
48 _self._status = 'finished'; // If the queue is empty, set the status to finished
49 return;
50 } // When step is an array Don’t follow this path
51 if( step.call ) { // If the object is a function object, execute the call method, and specify the internal this as _self.state, and continue calling_ in the callback function invoke
52 return step.call( _self.state,function _cont(state){
53 if( state ) _self.state = state;
54 _self._invoke();
55 }) ;
56 }
57 var finishedProcess = 0;
58 if( step.length === 0 ) _self._invoke(); // If the length of the array is 0, call _invoke
59 for(var i =0,l=step.length;i60 step[i].call(_self.state,function _joinWait(){
61 finishedProcess ;
62 if( finishedProcess == l ){
63 _self. _invoke();
64 }
65 });
66 }
67 }
68 });
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 });
80 };
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);
87 },
88 valueOf: function() {
89 return "#NamespaceObject<" this.fqn ">";
90 },
91 merge: function(obj) {
92 merge(this.stash,obj);
93 return this;
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;i104 retStash[ importNames[ i] ] = this.stash[ importNames[i] ];
105 }
106 return retStash;
107 }
108 });
109 var NamespaceObjectFactory = (function() {
110 var cache = {};
111 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) {
120 merge(this, {
121 namespaceObject: nsObj,
122 requires : [],
123 useList : [],
124 stash : {},
125 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 the array useList
133 var splitted = 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 function into the requires array
138 var context = this;
139 var require = NamespaceObjectFactory.create(fqn); // Get the specified NamespaceObject object. Previously generated objects can be obtained directly from the cache
140 require.call(this,function(state ){ // Call the call method of the NamespaceObject object
141 context.loadImport(require,importName);
142 $c();
143 });
144 });
145 return 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;i152 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;
168 this.defineCallback = function($c) { // Assign a value to defineCallback and define the callback function context, two objects, nsDef and nsObj.
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 });
195
196 var createNamespace = function(fqn){
197 return new NamespaceDefinition(
198 NamespaceObjectFactory.create(fqn || 'main')
199 );
200 };
201 merge(createNamespace, {
202 'Object' : NamespaceObjectFactory,
203 Definition: NamespaceDefinition,
204 Proc : createProcedure
205 });
206 return createNamespace;
207 })();

Additionally define the methods supported by Namespace:
Namespace.use
Namespace.fromInternal
Namespace.GET
Namespace.fromExternal
Copy code The code is 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) {
10 try { xhr = new ActiveXObject("Microsoft.XMLHTTP") } catch(e) {
11 throw new Error( "This browser does not support XMLHttpRequest." )
12 }
13 }
14 }
15 }
16 }
17 return xhr;
18 };
19 var isSuccessStatus = function(status) {
20 return (status >= 200 && status < 300) ||
21 status == 304 ||
22 status == 1223 ||
23 (!status && (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 callback(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 ) );
50 }else{
51 var pub = {};
52 pub[url] = 'loading error';
53 ns.provide(pub);
54 }
55 });
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;
75 callback();
76 };
77 scriptElement.src = url;
78 document.body.appendChild( scriptElement );
79 return scriptElement.src;
80 };
81 var domSrc = function(url){
82 return function(ns){
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] = callback;
93 };
94 return domSrc;
95 })();
96
97 try{ module.exports = Namespace; }catch(e){}

具体看一个例子:
复制代码 代码如下:

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
11 Namespace
12 .use('logtest')
13 .apply( function (ns) {
14 console.log(5);
15 ns.logtest.log();
16 });


1:Namespace('logtest') => new NamespaceDefinition(NamespaceObjectFactory.create('logtest'))
即生成一个NamespaceDefinition对象,该对象是由NamespaceObject对象来初始化的,该对象同时还有三个属性,Object,Definition,Proc。其值依次为 NamespaceObjectFactory,NamespaceDefinition,createProcedure函数对象类。Namespace('logtest') 返回的结果就是生成的NamespaceDefinition对象,然后调用其define方法,初始化defineCallback。此时仅仅是定义,不做具体的动作。

复制代码 代码如下:

166 define: function(callback){
167 var nsDef = this, nsObj = this.namespaceObject;
168 this.defineCallback = function($c) { // 给defineCallback赋值,同时定义一下该回调函数的上下文,nsDef和nsObj两个对象。
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 objects in the previously defined namespace, Namespace.use() => Namespace().use() => Namespace('main').use(). Initialize the requirements array when calling use.

Copy code The code is as follows:

131 use: function(syntax){ / / Use namespace
132 this.useList.push(syntax); // The namespace string is stored in the array useList
133 var splitted = syntax.split(/s /); // Namespace and its objects are used Separate by spaces
134 var fqn = splitted[0]; // Get namespace
135 var importName = splitted[1]; // Get objects in namespace
136 _assertValidFQN(fqn);
137 this.requires.push(function($c){ // Put a function into the requires array
138 var context = this;
139 var require = NamespaceObjectFactory.create(fqn); // Get the specified NamespaceObject Object, previously generated objects can be obtained directly from the cache
140 require.call(this,function(state){ // Call the call method of the NamespaceObject object
141 context.loadImport(require,importName);
142 $c();
143 });
144 });
145 return this;
146 },

3: Call main’s apply method. Take a look at the specific apply method
Copy the code The code is 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 }

Take out the objects in the requires array to generate a Proc object, and put the objects in the requires array into the queue steps , nsDef.defineCallback is also queued (undefined in this example), and the call method of Proc is called. The first parameter is nsDef, and the second parameter is the callback function.
Specific usage:
When defining Namespace, all definitions are placed in define and defined in the form of anonymous functions. function (ns) { // Specific implementation // Define an object that is exposed to the outside world. After using the nsName, the external party can call it through ns.nsName.key() ns.provide({ key : value});}
The advantage of using namespace.js is that all definitions are only executed when needed, that is, the definitions are parsed only when they are actually used.

ps: The specific internal calling relationship is still not clear. I will sort it out when I have time in the future. This article is too messy.
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Solve PHP error: The specified namespace class was not found Solve PHP error: The specified namespace class was not found Aug 18, 2023 pm 11:28 PM

Solve PHP error: The specified namespace class was not found. When developing using PHP, we often encounter various error messages. One of the common errors is "The specified namespace class was not found". This error is usually caused by the imported class file not being properly namespace referenced. This article explains how to solve this problem and provides some code examples. First, let’s take a look at an example of a common error message: Fatalerror:UncaughtError:C

How to use namespace in F3 framework? How to use namespace in F3 framework? Jun 03, 2023 am 08:02 AM

The F3 framework is a simple, easy-to-use, flexible and scalable PHPWeb framework. Its namespace (Namespace) mechanism provides us with a more standardized, more readable, and clearer code structure. In this article, we will explore how to use namespaces in the F3 framework. 1. What is a namespace? Namespaces are often used to solve the problem of naming conflicts in PHP. It can encapsulate one or more classes, functions or constants in a namespace, which is equivalent to adding a prefix to them. example

Design ideas and implementation methods of Redis namespace and expiration mechanism Design ideas and implementation methods of Redis namespace and expiration mechanism May 11, 2023 am 10:40 AM

Redis is an open source, high-performance key-value storage database. When using Redis for data storage, we need to consider the design of the key namespace and expiration mechanism to maintain Redis performance and data integrity. This article will introduce the design ideas and implementation methods of Redis' namespace and expiration mechanism. 1. Redis namespace design ideas In Redis, keys can be set arbitrarily. In order to facilitate the management and distinction of different data types, Redis introduces the concept of namespace. Life

C++ syntax error: undefined namespace used, how to deal with it? C++ syntax error: undefined namespace used, how to deal with it? Aug 21, 2023 pm 09:49 PM

C++ is a widely used high-level programming language. It has high flexibility and scalability, but it also requires developers to strictly master its grammatical rules to avoid errors. One of the common errors is "use of undefined namespace". This article explains what this error means, why it occurs, and how to fix it. 1. What is the use of undefined namespace? In C++, namespaces are a way of organizing reusable code in order to keep it modular and readable. You can use namespaces to make functions with the same name

Example of new features in PHP8: How to use namespaces and codes to better organize the code structure? Example of new features in PHP8: How to use namespaces and codes to better organize the code structure? Sep 11, 2023 pm 12:22 PM

Example of new features in PHP8: How to use namespaces and codes to better organize the code structure? Introduction: PHP8 is an important version of the PHP programming language, which introduces many exciting new features and improvements. One of the most important new features is namespaces. Namespaces are a way to organize your code into a better structure that avoids conflicts between classes, functions, and constants with the same name. In this article, we’ll look at how to leverage namespaces and codes to better structure your PHP8 code

PHP 5.3 new feature: How to use namespaces to resolve class name conflicts PHP 5.3 new feature: How to use namespaces to resolve class name conflicts Jul 30, 2023 pm 12:25 PM

New features of PHP5.3: How to use namespaces to solve class name conflicts Introduction: During the development of PHP, as projects become larger and more complex, class name conflicts also arise. In order to solve this problem, PHP5.3 version introduced the concept of namespace. Namespaces provide a way to organize related classes, functions, and constants together to avoid naming conflicts. This article will introduce in detail the concept of PHP namespaces and how to use namespaces to solve class name conflicts, with code examples.

Best practices for PHP autoloading: ensuring stability and performance Best practices for PHP autoloading: ensuring stability and performance Mar 02, 2024 pm 09:10 PM

PHP Autoloading Overview Autoloading is a mechanism for automatically loading classes and their dependencies before use. In PHP, this is achieved by using the __autoload() function or an autoloader such as Composer. Proper autoloading settings are critical to ensuring the stability and performance of your codebase. PSR-4 automatic loading standard PSR-4 is the automatic loading standard defined by PHP-FIG. It is based on namespace and directory structure conventions to simplify class file lookup. To comply with PSR-4: define a root namespace (e.g. MyApp). Use backslash() as namespace separator. Use lowercase letters to represent namespace elements. Create a corresponding directory for each namespace element. General essay

How to use PHP7's namespace and automatic loading mechanism to organize the structure of the code? How to use PHP7's namespace and automatic loading mechanism to organize the structure of the code? Oct 20, 2023 am 08:57 AM

How to use PHP7's namespace and automatic loading mechanism to organize the structure of the code? Abstract: With the launch of PHP7, namespace and automatic loading mechanism have become important features that cannot be ignored in PHP development. This article will introduce how to use PHP7's namespace and automatic loading mechanism to organize the structure of the code, and illustrate it through specific code examples. 1. What is a namespace? Namespace is a mechanism introduced in PHP7 to resolve naming conflicts that may occur between different class libraries or code files. via namespace

See all articles