如何创建JavaScript中的命名空间,以便我的对象和函数不会被其他同名的对象和函数覆盖?我已经使用了以下代码:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
有没有更优雅或更简洁的方法来做这件事?
如何创建JavaScript中的命名空间,以便我的对象和函数不会被其他同名的对象和函数覆盖?我已经使用了以下代码:
if (Foo == null || typeof(Foo) != "object") { var Foo = new Object();}
有没有更优雅或更简洁的方法来做这件事?
这里是他们的示例,展示如何声明私有和公共属性和函数。所有操作都是通过自执行匿名函数完成的。
(function( skillet, $, undefined ) {
//Private Property
var isHot = true;
//Public Property
skillet.ingredient = "Bacon Strips";
//Public Method
skillet.fry = function() {
var oliveOil;
addItem( "\t\n Butter \n\t" );
addItem( oliveOil );
console.log( "Frying " + skillet.ingredient );
};
//Private Method
function addItem( item ) {
if ( item !== undefined ) {
console.log( "Adding " + $.trim(item) );
}
}
}( window.skillet = window.skillet || {}, jQuery ));
skillet.fry()
或skillet.ingredients
即可。//Adding new Functionality to the skillet
(function( skillet, $, undefined ) {
//Private Property
var amountOfGrease = "1 Cup";
//Public Method
skillet.toString = function() {
console.log( skillet.quantity + " " +
skillet.ingredient + " & " +
amountOfGrease + " of Grease" );
console.log( isHot ? "Hot" : "Cold" );
};
}( window.skillet = window.skillet || {}, jQuery ));
undefined
参数第三个
undefined
参数是变量值undefined
的来源。我不确定它今天是否仍然相关,但在使用旧版本浏览器 / JavaScript标准(ECMAScript 5,JavaScript <1.8.5〜Firefox 4),全局作用域变量undefined
是可写的,因此任何人都可以重写其值。当未传递值时,第三个参数(undefined)会创建一个名为undefined
的变量,该变量作用域限定于命名空间/函数中。因为在创建名称空间时没有传递值,所以它默认为值undefined
。
undefined
参数是值为undefined
的变量源。在使用旧版浏览器/JavaScript标准(ECMAScript 5,JavaScript<1.8.5〜Firefox 4)时,全局范围的变量undefined
是可写的,因此任何人都可以重写其值。添加第三个额外的参数,您没有传递它的值为undefined
,因此您正在创建命名空间范围的undefined
,它不会被外部源重写。 - mrówawindow.skillet = window.skillet || {}
的好处在于,它允许多个脚本安全地添加到同一个命名空间中,即使它们不提前知道执行顺序。这样做的好处是,无论您想随意重新排序脚本引用而不会破坏代码,还是想使用 async 属性 异步加载脚本并不确定执行顺序,都可以帮助您。详情请参见 https://dev59.com/4Gw15IYBdhLWcg3wuuCn。 - Mark Amery我喜欢这个:
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();
MyApp.Views.Profile = {}
而不是MyApp.users = {}
和MyViews.Profile = {}
。并不一定意味着只能有两个级别的深度。 - alexns().publicFunction()
,而是可以直接使用 ns.publicFunction()
? - John Kraftfunction
关键字前面有new
关键字。基本上,它正在声明一个匿名函数(作为函数,它也是一个构造函数),然后立即使用new
将其作为构造函数调用。因此,存储在ns
中的最终值是该匿名构造函数的(唯一)实例。希望这样说得通。 - Ionuț G. Stan有更优雅或简洁的方法吗?
有。例如:
var your_namespace = your_namespace || {};
然后你就可以拥有了
var your_namespace = your_namespace || {};
your_namespace.Foo = {toAlert:'test'};
your_namespace.Bar = function(arg)
{
alert(arg);
};
with(your_namespace)
{
Bar(Foo.toAlert);
}
var your_namespace = your_namespace = your_namespace || {}
- Sriram我通常在一个闭包中构建它:
var MYNS = MYNS || {};
MYNS.subns = (function() {
function privateMethod() {
// Do private stuff, or build internal.
return "Message";
}
return {
someProperty: 'prop value',
publicMethod: function() {
return privateMethod() + " stuff";
}
};
})();
自从我写下这句话以来,我的风格已经有了微妙的变化,现在我发现自己会像这样编写闭包:
var MYNS = MYNS || {};
MYNS.subns = (function() {
var internalState = "Message";
var privateMethod = function() {
// Do private stuff, or build internal.
return internalState;
};
var publicMethod = function() {
return privateMethod() + " stuff";
};
return {
someProperty: 'prop value',
publicMethod: publicMethod
};
})();
以这种方式,我发现公共API和实现更易于理解。将返回语句视为对实现的公共接口。
MYNS.subns = MYNS.subns || {}
的值? - Paranoid Androidvar foo = function
和function foo
是类似的,因为它们都是私有的;但由于JavaScript的动态类型特性,后者稍微更快,因为它在大多数解释器的流水线中跳过了一些指令。对于var foo
,必须调用类型系统才能找到要分配给该变量的类型,而对于function foo
,类型系统自动知道它是一个函数,因此跳过了几个函数调用,这意味着CPU指令的少数调用,例如jmp
,pushq
,popq
等,这会使CPU流水线变短。 - Braden Bestfunction foo
语法更易读。而且我仍然喜欢我的版本。 - Braden Best因为您可能会编写不同的JavaScript文件,然后将它们合并或不合并到应用程序中,所以每个文件需要能够恢复或构建命名空间对象,而不会损坏其他文件的工作...
一个文件可能打算使用命名空间namespace.namespace1
:
namespace = window.namespace || {};
namespace.namespace1 = namespace.namespace1 || {};
namespace.namespace1.doSomeThing = function(){}
另一个文件可能想要使用命名空间 namespace.namespace2
:
namespace = window.namespace || {};
namespace.namespace2 = namespace.namespace2 || {};
namespace.namespace2.doSomeThing = function(){}
这两个文件可以共存或分开而不会冲突。
/**
* My JavaScript application
*
* @module myapp
*/
/** @namespace Namespace for MYAPP classes and functions. */
var MYAPP = MYAPP || {};
/**
* A maths utility
* @namespace MYAPP
* @class math_stuff
*/
MYAPP.math_stuff = {
/**
* Sums two numbers
*
* @method sum
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} Sum of the inputs
*/
sum: function (a, b) {
return a + b;
},
/**
* Multiplies two numbers
*
* @method multi
* @param {Number} a First number
* @param {Number} b Second number
* @return {Number} The inputs multiplied
*/
multi: function (a, b) {
return a * b;
}
};
/**
* Constructs Person objects
* @class Person
* @constructor
* @namespace MYAPP
* @param {String} First name
* @param {String} Last name
*/
MYAPP.Person = function (first, last) {
/**
* First name of the Person
* @property first_name
* @type String
*/
this.first_name = first;
/**
* Last name of the Person
* @property last_name
* @type String
*/
this.last_name = last;
};
/**
* Return Person's full name
*
* @method getName
* @return {String} First name + last name
*/
MYAPP.Person.prototype.getName = function () {
return this.first_name + ' ' + this.last_name;
};
我使用以下方法:
var myNamespace = {}
myNamespace._construct = function()
{
var staticVariable = "This is available to all functions created here"
function MyClass()
{
// Depending on the class, we may build all the classes here
this.publicMethod = function()
{
//Do stuff
}
}
// Alternatively, we may use a prototype.
MyClass.prototype.altPublicMethod = function()
{
//Do stuff
}
function privateStuff()
{
}
function publicStuff()
{
// Code that may call other public and private functions
}
// List of things to place publically
this.publicStuff = publicStuff
this.MyClass = MyClass
}
myNamespace._construct()
// The following may or may not be in another file
myNamespace.subName = {}
myNamespace.subName._construct = function()
{
// Build namespace
}
myNamespace.subName._construct()
然后可以使用外部代码:
var myClass = new myNamespace.MyClass();
var myOtherClass = new myNamepace.subName.SomeOtherClass();
myNamespace.subName.publicOtherStuff(someParameter);
ns = ns || {}
看起来更加严谨,但它可能会导致其他意想不到的结果。 - AnthonyWJonesns = ns || {}
会产生什么意外的结果?更为谨慎的方法可能是var n = n && n.name === "NSNAME" ? n : { name: "NSNAME"};
。 - Brett Ryan这是对user106826提供的Namespace.js链接的跟进。该项目似乎已经迁移到GitHub,现在位于smith/namespacedotjs。
我一直在为我的小型项目使用这个简单的JavaScript帮助程序,到目前为止,它似乎轻巧而且足够灵活,可以处理命名空间和加载模块/类。如果它可以让我将包导入到我选择的命名空间中,而不仅仅是全局命名空间,那就太好了……唉,但这已经不是重点了。
它允许您声明命名空间,然后在该命名空间中定义对象/模块:
Namespace('my.awesome.package');
my.awesome.package.WildClass = {};
另一个选择是一次性声明命名空间及其内容:
Namespace('my.awesome.package', {
SuperDuperClass: {
saveTheDay: function() {
alert('You are welcome.');
}
}
});
如果需要更多的用法示例,请查看源代码中的example.js文件。
示例:
var namespace = {};
namespace.module1 = (function(){
var self = {};
self.initialized = false;
self.init = function(){
setTimeout(self.onTimeout, 1000)
};
self.onTimeout = function(){
alert('onTimeout')
self.initialized = true;
};
self.init(); /* If it needs to auto-initialize, */
/* You can also call 'namespace.module1.init();' from outside the module. */
return self;
})()
如果想将一个变量声明为私有变量,可以选择性地声明一个local
变量same
,类似于self
并将local.onTimeout
赋值给它。