在jQuery中创建命名空间是否可能?

52

YUI有一种很好的方式在javascript中为您的方法等创建命名空间。

jQuery有类似的东西吗?

9个回答

39

lpfavreau 提供了一种解决方案,可以通过扩展 jQuery 对象来添加自己的方法(以便这些功能适用于实际的 jQuery 对象上下文)。

如果你只想给你的代码加上命名空间,可以像这样使用美元符号:

$.myNamespace = { .. };
或者是"jQuery":
jQuery.myNamespace = { .. };

选用命名空间时要小心,因为这可能会覆盖现有的jQuery方法(建议首先在jQuery代码中搜索以避免这种情况发生)。

你可以通过此链接进行了解:http://www.zachleat.com/web/2007/08/28/namespacing-outside-of-the-yahoo-namespace/

看一下创建自己的函数以复制YUI所做的事情有多容易:

// include jQuery first.
jQuery.namespace = function() {
    var a=arguments, o=null, i, j, d;
    for (i=0; i<a.length; i=i+1) {
        d=a[i].split(".");
        o=window;
        for (j=0; j<d.length; j=j+1) {
            o[d[j]]=o[d[j]] || {};
            o=o[d[j]];
        }
    }
    return o;
};

// definition
jQuery.namespace( 'jQuery.debug' );
jQuery.debug.test1 = function()
{
    alert( 'test1 function' );
};
jQuery.debug.test2 = function()
{
    alert( 'test2 function' );
};
// usage
jQuery.debug.test1();
jQuery.debug.test2();

12

这是我为我的插件创建命名空间的方法:

(function ($) {
    // do not overwrite the namespace, if it already exists
    $.MyNamespace = $.MyNamespace || {};
    $.MyNamespace.MyPlugin = function () {/*here's the logic*/}
})($);

之后:

$.MyNamespace.MyPlugin ();

这就是你真正需要的。有时候这可能会变得有点繁重/手动...如果您需要在多个文件中发生定义,您可能希望自动化其中的一些内容。 - 1nfiniti
在jQuery的上下文中,有正确和错误的方法来处理这个问题。这是一个错误的例子。请参阅jQuery.extendjQuery.fn.extend - Madbreaks

5

jQuery有很多扩展基础功能的插件。这里有一个用于简化命名空间的插件


4
如果您想以这种方式使用jQuery:

$("*").namespace.do();

目前没有插件可以做到这一点。(我找不到约翰·雷西格的jquery.space插件,它似乎在jQuery 1.4中停止工作了,也找不到Gilberto Saraiva插件按预期工作的情况)。我很高兴查看约翰的函数以了解为什么它停止工作以及如何使其工作,坦率地说,这将是创建清晰的命名空间的最佳方法。

根据http://malnotna.wordpress.com/2009/01/12/jquery-namespace-support/的说法,另一种方法是使用Ariel Flesler的jQuery.Modularize进行命名空间设置:

$("*").namespace().do()

但是这样的语法并不“美观”。我们还需要将一个函数的结果传递给另一个函数。

我的命名空间创建方法是将命名空间放在 $ 的开头,而不是放在结尾,因此我们的 $('*').namespace 语法变成了:

$.namespace("*").do()

奇怪的是,我不知道为什么这种方法没有被提到,因为它可以轻松地创建未经过多余函数覆盖的清晰命名空间(通过使用$.sub())。此外,使其工作并不需要任何东西。所以:

(function($){
    $.namespace = $.sub();
    $.fn.test = function(){ return 1 };              
    $.namespace.fn.test = function() { return 2};
})(jQuery);

console.log($('*').test(), $.namespace('*').test());

现在你已经准备好了。


1
很遗憾,$.sub在jQuery 1.9以上的版本中已被移除:/ - Félix Veysseyre

4

namespace插件是完全不必要的! 世界上最古老的技巧,使用arguments.callee,Function.prototype,然后调用一个新的Function实例,可以让您使用$.fn.extend创建嵌套命名空间!

这里是一个简单明了的例子:

    ;(function($){
    var options= {
        root: function(){ //you don't have to call it 'root', of course :)
            //identify the function from within itself with arguments.callee
            var fn= arguments.callee;

            //'this' at this level is the jquery object list matching your given selector
            //we equate fn.prototype to this 
            //thus when we call a new instance of root, we are returned 'this'
            fn.prototype= this;

            fn.value= function(){
                //Note: "new this" will work in the below line of code as well,
                //because in the current context, 'this' is fn;
                //I use fn to make the code more intuitive to understand;
                var context= new fn; 

                console.log(context, fn.prototype); //test
                return context.html(); //test
            }

            return this;
        }
    }

    //you can obviously append additional nested properties in this manner as well
    options.root.position= function(){
        var context= new this; //in this context, fn is undefined, so we leverage 'this'

        console.log(context, this.prototype); //test
        return context.offset(); //test
    }

    //don't forget to extend in the end :)
    $.fn.extend(options);

})(jQuery);

;$(function(){
    var div= $('div#div')
        .root();

    console.log(div.root.value());
    console.log(div.root.position());
});

7
arguments.calleearguments.caller 在 ECMAScript 5 中已经被弃用,如果在严格模式下使用将会导致错误。MDN - ObjectiveCat
15
我质疑这是世界上最古老的花招。 - mxcl
@MaxHowell 绝对不比从帽子里变出一只兔子的年龄还大。 - Yatrix

2

请查看这篇博客:http://javascriptweblog.wordpress.com/2010/12/07/namespacing-in-javascript/

我之前使用过自调用动态命名空间:

var myApp = {};
(function(context) {
    var id = 0;

    context.next = function() {
        return id++;
    };

    context.reset = function() {
        id = 0;
    } 
})(myApp); 

window.console && console.log(
    myApp.next(),
    myApp.next(),
    myApp.reset(),
    myApp.next()
); //0, 1, undefined, 0

这并没有回答提问者的问题。 - Madbreaks

2
根据你想要做什么,jQuery的插件架构可能是你正在寻找的:
$.fn.myPlugin = function() {
  return $(this).each(function() {
    // do stuff
  });
};

或者...
$.fn.myPlugin = function() {
  var myNamespace = {
    // your stuff
  };
};

这真的取决于你想要做什么。

http://docs.jquery.com/Plugins/Authoring


1
所有的功劳归功于 @Diego Fluery,我只是拿了他的幻灯片,并制作了可运行的代码原型,但如果你选择这条路线,它可能会为你节省几分钟时间。
<!DOCTYPE html>
<html>
<head>
<script type="application/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="application/javascript">

    $(document).ready(function() {
        (function () {
            $.fn.AppRedirect = function() {
                this.sendRequest = parts.sendRequest;
                this.doRedirect = parts.doRedirect;

                return this;
            }

            var parts = {

                doRedirect: function() {
                    console.log('doRedirect');
                },

                sendRequest: function() {
                    console.log('sendRequest');
                }

            };
        })();

        $("body").AppRedirect().sendRequest();
        $("body").AppRedirect().doRedirect();
    });     

</script>
</head>
<body>
</body>
</html>

0

使用jQuery 3.6.0

我知道这个问题很古老,而且这个答案可能不是针对OP想要的精确级别。然而,现在jQuery中函数级别的命名空间已经被简化了。

例如:

$("body").off(".myNamespace"); /* prevent duplicate listeners in the namespace */
$("body").on("click.myNamespace", "tr.dtrg-start", function() {
...
}

https://api.jquery.com/event.namespace/

https://api.jquery.com/on/#event-names


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