如何在 JavaScript 中创建自定义命名空间或类

4

我想创建自己的命名空间,类似于JQuery$

 (function(app) {
     app.fn.log = function(data) {
          console.log(data);
        };
 }(app));

 app.log("data");

但是这段代码返回了一个错误 - 未捕获的引用错误:app未定义

我该如何创建自己的命名空间?


那么,app在哪里定义的?该函数需要一个app参数,而你传递了一个不存在的app变量... - elclanrs
我不知道应该在哪里和如何实现它。 - Ata
看看这个是否有帮助 http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript - elclanrs
我认为你应该阅读关于JavaScript的书籍,Codeacademy)) - Farkhat Mikhalko
我可以使用 {} 来定义它,而且它能够很好地工作,但我不能仅使用自定义命名空间。 - Ata
3个回答

3
在JavaScript中实现命名空间的常见方法是利用具有立即执行函数作用域的模块模式。这还允许您传递具有非冲突名称的对象并使用您喜欢的参数化名称,例如$,如下所示:
//Global script declaration
var NAMESPACE = {};

//Check if you need to initialize your namespace
NAMESPACE.FooSpace = NAMESPACE.FooSpace || {};

//Some other script
NAMESPACE.FooSpace = (function($) {
    function Foo1() {
    }

    function Foo2() {
        return $.getSomething(); //some existing function inside of someObjectWithANonConflictingName object
    }    

    return { Foo1: Foo1, Foo2: Foo2 };
})(someObjectWithANonConflictingName);

//somewhere else in code (call as a constructor function)
var foo = new NAMESPACE.FooSpace.Foo1();
//somewhere else in code (call as regular function)
var foo2 = Foo2();
  • 采用这种方法可以避免命名冲突,因为您只需要将函数和变量的名称添加到NAMESPACE对象中,即可拥有重叠的名称。
  • 而且,它还可以让您将变量或函数重命名为与流行库冲突的名称,从而获得额外的好处。
  • 此外,这有助于真正减少全局命名空间,因为它全部保存在NAMESPACE对象中。
  • 它为您提供了将某些内容附加到window对象的替代选项(有些人认为这样做不好)。

2
window.app = {};

(function(app) {
    app.log = function(data) {
         console.log(data);
       };
}(app));

app.log("data");

jQuery对它的fn有一些不同的处理方式:当您使用$('selector')语法查找需要处理的元素时,jQuery会返回一个特殊的wrapper,其中包含了您添加的所有fn.func样式定义以及内置函数。

因此,如果您需要实现某种可扩展性,您应该首先考虑这种包装。例如:

window.app = function(p) {

    // do whatever you need

    var wrapper = {
        // standard common fields
    };

    if (app.fn) {
        // extend wrapper with app.fn
    }

    return wrapper;
};

顺便问一下,您想解决什么问题?

在您的情况下,有一个例外,因为在匿名函数执行时 app 未被定义。


谢谢,是的,现在它运行得很好,但我希望您知道我的另一个问题,正如您所看到的 console.log(data); 在浏览器中显示了调用此函数的行,请问有没有办法传递并显示由函数调用的行?我的意思是显示我调用 app.log('data'); 的那一行。 - Ata
什么是 line?是行号吗? - Sergey Metlov
很遗憾,这是不可能的。 - Sergey Metlov

1
你的语法没问题,但是你需要定义一个app。你将app作为参数传递给你的IIFE,但是app没有被定义!如果你想把jQuery作为app访问,只需像这样调用你的IIFE并传递jQuery对象:
(function(app) {
     app.fn.log = function(data) {
          console.log(data);
        };
 }($)); // where $ is your jQuery.

并且

$.log("data");

注意!log函数将在IIFE的作用域内外都可用!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接