引入Namespace的目的

JavaScript中引入NamespaceC#一样,都是为了避免命名冲突。但是Js又有些特殊:

js解释执行,如果后面定义了同名的变量会覆盖前面变量,并用应用新定义变量的语义。这在Js中合法,没有错误提示,因此bug很难找。

可以想象,我调用了一个第三方模块,如果这个模块没有定义在Namespace中,我定义的变量和函数很可能就覆盖了第三方的同名符号。

模块原则

a module should never add more than a single symbol to the global namespace

只有这样才能保证模块的重用性,MicrosoftAJax就是这样实现的。除了几个以$开头的全局符号,其余符号都定义在Sys命名空间中。

$符号

MA.js,部分违反了上面的原则,但是它对违反原则的变量命名都以$开头。这样也对模块的调用者有个约定,即:$开头的变量属于全局名称空间,调用者如果也以$命名变量必须自觉保证没有冲突。可以看到Animaions.js有类似用法。

类似的约定还有:以_开头的变量为私有,不应该调用。他们的实现可能会变化,调用者如果应用,必须做层封装。

Namespace通常实现

对于JS这种动态语言来说,实现namespace很简单,定义一个对象变量即可。

如:

定义了Sys名称空间,在其中定义了DebugStringBuilder对象。

上面的定义过于简单,实际上还要做一下检测,看看是否已经定义过相同的名称空间,如果有跑出异常或者用已经存在的名称空间;是否namespace是对象,不是也抛异常。

 

Ajax-JavaScript-namespacevar Sys= undefined;
Ajax-JavaScript-namespace

上面是比较严格的实现,MicrosoftAjax.js,就是用上面的逻辑,只是他代码更复杂些。

注:在Antechinus中如果不指定undefined,会出错。但是Js语法没有这种要求。猜测Antechinus可能会先读取Sys,读没有声明的变量会有异常。

MicrosoftAjax.js实现

MA中注册Namespace,通过循环的方式,window对象保持对rootNamespace的引用,rootNamespace又引用子空间。形成一条链。

如注册:Type.registerNamespace('My.I.M');

会注册下面三个空间:MyMy.IMy.I.M。其中MyrootNamespaceMyMy.I被隐含注册,可以直接使用。

MA的实现看起来很复杂,但是只要注意下面几条还是很容易看懂的:

利用window

var rootObject = window;

在第一次循环中rootObject一直指向window,如果根没有被注册则在window中注册根命名空间。结果是:window[‘My’]={},window===rootObject

第二次循环,winodw指向rootObject[‘My’]。以My为根,注册I。结果:window[‘My’][‘I’]={}window===rootObject[‘My’]

第三次注册My.I.M

因为用到了windowRegisterNamespace也失去了通用性。

Eval

值支持primitive value

eval(code)

code

A string that contains the JavaScript expression to be evaluated or the statements to be executed.

Returns

The value of the evaluated code, if any.

类似数组的语法访问对象

winodw[‘Sys’][‘Net’]

代码:

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-11-20
  • 2021-11-20
  • 2021-10-07
  • 2021-06-23
  • 2021-12-13
猜你喜欢
  • 2021-10-17
  • 2021-10-18
  • 2021-05-20
  • 2021-10-22
  • 2021-12-22
  • 2021-08-08
相关资源
相似解决方案