namespace.js Javascript的命名空间库_javascript技巧
github:https://github.com/hirokidaichi/namespace-js
定义Namespace对象:
var Namespace
现在来具体看一下Namespace对象的定义,它是一个NamespaceDefinition对象。该对象是一个函数对象(NamespaceDefinition对象的构造函数,如果不给参数的话就默认生成一个main的命名空间),还有三个属性,Object,Definition,Proc。其值依次为NamespaceObjectFactory,NamespaceDefinition,createProcedure函数对象类。
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:根据fqn生成NamespaceObject对象。
NamespaceObjectFactory对象只有一个create方法,参数就是命名空间的名字(Fully Qualified Name)。该方法有一个闭包环境,该环境里有一个cache变量用于缓存所有生成的NamespaceObject对象。
一个NamespaceObject对象包含有三个属性,stash(记录当前namespace),fqn(namespace名字),proc(createProcedure对象)。方法包括:enqueue,call,valueof,merge,getStash,getExport
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";
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;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:
该对象包括5个属性,namespaceObject,requires,useList,stash,defineCallback。并提供了相关的方法:use,_mergeStashWithNS,loadImport,define,getStash,valueOf,apply
该对象是namespace库的核心,它提供了所有需要的方法。
初始化的时候,在NamespaceObject的proc的steps队列里追加一个函数对象,该函数将调用apply方法。
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;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 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){ // 把source的所有自身属性copy到target中去,并返回target对象 4 for(var p in source)
5 if(source.hasOwnProperty( p )) target[p] = source[p];
6 return target;
7 };
8 var _assertValidFQN = function(fqn){ // 验证namespace名字的有效性,必须是小写英数字,下划线和点
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 : {}, // 状态
15 steps : [], // 存储状态的数组
16 _status: 'init'
17 });
18 };
19 merge(Procedure.prototype, {
20 next: function(state){ // 如果state有值,存入到steps队列队尾,然后返回this
21 if(state) this.enqueue(state);
22 return this;
23 },
24 isRunning: function(){ // 判定是否为running状态
25 return (this._status === 'running');
26 },
27 enqueue: function(state){ // 这里其实是用数组steps来模拟队列,enqueue就是从队尾入队列
28 this.steps.push(state);
29 },
30 dequeue: function(){ // dequeue就是从对头出队列
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 || {}; // 保存当前state(NamespaceDefinition对象)
37 this.enqueue(function($c){ // 函数入队列steps
38 $c(); // 执行传进来的函数
39 if(callback)callback(this); // 如果存在回调函数的,执行回调函数
40 });
41 this._status = 'running'; // 设置状态为running
42 this._invoke(); // 调用_invoke
43 },
44 _invoke: function(){
45 var _self = this;
46 var step = _self.dequeue(); // 对象出队列(FIFO)
47 if( !step ){
48 _self._status = 'finished'; // 如果队列为空,则设置状态为finished
49 return;
50 } // step是数组的情况下不走这条路径
51 if( step.call ) { // 如果该对象是函数对象的时候,则执行该call方法,并指定内部this为_self.state,回调函数里面继续调用_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(); // 如果该数组长度为0,则调用_invoke
59 for(var i =0,l=step.length;i
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";
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;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){ // 使用namespace
132 this.useList.push(syntax); // 该namespace字符串存入数组useList
133 var splitted = syntax.split(/\s+/); // namespace和它的对象使用空格分开
134 var fqn = splitted[0]; // 取得namespace
135 var importName = splitted[1]; // 取得namespace中的对象
136 _assertValidFQN(fqn);
137 this.requires.push(function($c){ // 放一个函数到requires数组中
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();
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;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) { // 给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 },
180 getStash: function(){
181 return this.stash;
182 },
183 valueOf: function(){
184 return "#NamespaceDefinition 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 })();
追加定义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( "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 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:使用之前定义的namespace里面的对象,Namespace.use() => Namespace().use() => Namespace('main').use()。调用use的时候初始化requires数组。
131 use: function(syntax){ // 使用namespace
132 this.useList.push(syntax); // 该namespace字符串存入数组useList
133 var splitted = syntax.split(/\s+/); // namespace和它的对象使用空格分开
134 var fqn = splitted[0]; // 取得namespace
135 var importName = splitted[1]; // 取得namespace中的对象
136 _assertValidFQN(fqn);
137 this.requires.push(function($c){ // 放一个函数到requires数组中
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();
143 });
144 });
145 return this;
146 },
3:调用main的apply方法。看一下具体的apply方法
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 }
取出requires数组里面的对象生成Proc对象,并把该requires数组里的对象入队列steps中,还有nsDef.defineCallback也入队列(此例中为undefined),调用Proc的call方法。第一个参数是nsDef,第二个参数是回调函数。
具体使用方法:
在定义Namespace的时候,所有的定义放在define里面,并且以匿名函数的形式定义。function (ns) { // 具体的实现 // 定义对外公开的对象,外部在use该nsName之后,就可以通过ns.nsName.key()来调用它 ns.provide({ key : value});}
使用namespace.js的好处,所有的定义都是在需要的时候才开始执行的,也就是在具体使用的时候才开始解析定义。
ps:具体内部调用关系还是没有弄明白,今后有时间再整理,这篇太乱了。

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



PHP-Fehler beheben: Die angegebene Namespace-Klasse wurde nicht gefunden. Bei der Entwicklung mit PHP treten häufig verschiedene Fehlermeldungen auf. Einer der häufigsten Fehler ist „Die angegebene Namespace-Klasse wurde nicht gefunden“. Dieser Fehler wird normalerweise dadurch verursacht, dass auf die importierte Klassendatei nicht ordnungsgemäß auf den Namespace verwiesen wird. In diesem Artikel wird erläutert, wie Sie dieses Problem lösen können, und es werden einige Codebeispiele bereitgestellt. Schauen wir uns zunächst ein Beispiel für eine häufige Fehlermeldung an: Fatalerror:UncaughtError:C

Das F3-Framework ist ein einfaches, benutzerfreundliches, flexibles und skalierbares PHPWeb-Framework. Sein Namespace-Mechanismus bietet uns eine standardisiertere, besser lesbare und klarere Codestruktur. In diesem Artikel untersuchen wir, wie Namespaces im F3-Framework verwendet werden. 1. Was ist ein Namespace? Namespaces werden häufig verwendet, um das Problem von Namenskonflikten in PHP zu lösen. Er kann eine oder mehrere Klassen, Funktionen oder Konstanten in einem Namespace kapseln, was dem Hinzufügen eines Präfixes entspricht. Beispiel

Redis ist eine Open-Source-Hochleistungs-Schlüsselwertspeicherdatenbank. Wenn wir Redis zur Datenspeicherung verwenden, müssen wir das Design des Schlüsselnamensraums und des Ablaufmechanismus berücksichtigen, um die Leistung und Datenintegrität von Redis aufrechtzuerhalten. In diesem Artikel werden die Designideen und Implementierungsmethoden des Redis-Namespace und des Ablaufmechanismus vorgestellt. 1. Designideen für Redis-Namespaces In Redis können Schlüssel beliebig festgelegt werden. Um die Verwaltung und Unterscheidung verschiedener Datentypen zu erleichtern, führt Redis das Konzept des Namespace ein. Leben

C++ ist eine weit verbreitete Programmiersprache auf hoher Ebene. Sie verfügt über eine hohe Flexibilität und Skalierbarkeit, erfordert jedoch auch, dass Entwickler ihre grammatikalischen Regeln strikt beherrschen, um Fehler zu vermeiden. Einer der häufigsten Fehler ist die „Verwendung eines undefinierten Namespace“. In diesem Artikel wird erläutert, was dieser Fehler bedeutet, warum er auftritt und wie er behoben werden kann. 1. Wozu dient ein undefinierter Namespace? In C++ sind Namespaces eine Möglichkeit, wiederverwendbaren Code zu organisieren, um ihn modular und lesbar zu halten. Sie können Namespaces verwenden, um Funktionen mit demselben Namen zu erstellen

Beispiel für neue Funktionen in PHP8: Wie kann man Namespaces und Codes verwenden, um die Codestruktur besser zu organisieren? Einführung: PHP8 ist eine wichtige Version der Programmiersprache PHP, die viele aufregende neue Funktionen und Verbesserungen einführt. Eine der wichtigsten Neuerungen sind Namespaces. Namespaces sind eine Möglichkeit, Ihren Code in einer besseren Struktur zu organisieren, die Konflikte zwischen Klassen, Funktionen und Konstanten mit demselben Namen vermeidet. In diesem Artikel schauen wir uns an, wie Sie Namespaces und Codes nutzen können, um Ihren PHP8-Code besser zu strukturieren

PHP ist eine äußerst flexible Programmiersprache mit einem breiten Anwendungsspektrum. Um Namenskonflikte zu vermeiden und die Lesbarkeit und Wartbarkeit des Codes zu verbessern, führt PHP in der PHP-Entwicklung das Konzept des Namespace ein. Namespaces helfen Entwicklern, denselben Klassen- oder Funktionsnamen im selben Projekt ohne Konflikte zu verwenden. In diesem Artikel werden die Konfiguration von Namespaces in PHP und allgemeine Anwendungsbeispiele vorgestellt. 1. So konfigurieren Sie den PHP-Namespace, indem Sie am Anfang der Datei den Namespace verwenden.

Neue Funktionen von PHP5.3: Verwendung von Namespaces zur Lösung von Klassennamenkonflikten Einführung: Während der Entwicklung von PHP treten mit zunehmender Größe und Komplexität von Projekten auch Klassennamenkonflikte auf. Um dieses Problem zu lösen, wurde in der PHP5.3-Version das Konzept des Namespace eingeführt. Namespaces bieten eine Möglichkeit, zusammengehörige Klassen, Funktionen und Konstanten zu organisieren, um Namenskonflikte zu vermeiden. In diesem Artikel werden das Konzept von PHP-Namespaces und die Verwendung von Namespaces zur Lösung von Klassennamenkonflikten anhand von Codebeispielen ausführlich vorgestellt.

So beheben Sie PHP-Namespace-Fehler und generieren entsprechende Fehlermeldungen. PHP ist eine weit verbreitete serverseitige Skriptsprache, die zur Entwicklung von Webanwendungen verwendet wird. In PHP ist Namespace (Namespace) ein Mechanismus zum Verwalten und Organisieren von Code, der Namenskonflikte vermeiden und die Lesbarkeit und Wartbarkeit des Codes verbessern kann. Allerdings führt die Komplexität der Namespace-Definition und -Nutzung manchmal zu Fehlern. In diesem Artikel werden einige Methoden zum Beheben von PHP-Namespace-Fehlern und zum Generieren entsprechender Fehlermeldungen vorgestellt. 1. Namensraum
