为什么 Backbone.js 代码前面有 (function($){...?

发布于 2024-12-25 06:37:31 字数 1417 浏览 0 评论 0原文

这是 Backbone.js 代码的示例(取自 this 教程):

// **This example illustrates the binding of DOM events to View methods.**
//
// _Working example: [2.html](../2.html)._  
// _[Go to Example 3](3.html)_

//
(function($){
  var ListView = Backbone.View.extend({
    el: $('body'), // el attaches to existing element
    // `events`: Where DOM events are bound to View methods. Backbone doesn't have a separate controller to handle such bindings; it all happens in a View.
    events: {
      'click button#add': 'addItem'
    },
    initialize: function(){
      _.bindAll(this, 'render', 'addItem'); // every function that uses 'this' as the current object should be in here

      this.counter = 0; // total number of items added thus far
      this.render();
    },
    // `render()` now introduces a button to add a new list item.
    render: function(){
      $(this.el).append("<button id='add'>Add list item</button>");
      $(this.el).append("<ul></ul>");
    },
    // `addItem()`: Custom function called via `click` event above.
    addItem: function(){
      this.counter++;
      $('ul', this.el).append("<li>hello world"+this.counter+"</li>");
    }
  });

  var listView = new ListView();      
})(jQuery);

我不明白为什么它前面必须有一个 (function($){...

有人能给我解释一下吗?

This is an example of Backbone.js code (taken from this tutorial):

// **This example illustrates the binding of DOM events to View methods.**
//
// _Working example: [2.html](../2.html)._  
// _[Go to Example 3](3.html)_

//
(function($){
  var ListView = Backbone.View.extend({
    el: $('body'), // el attaches to existing element
    // `events`: Where DOM events are bound to View methods. Backbone doesn't have a separate controller to handle such bindings; it all happens in a View.
    events: {
      'click button#add': 'addItem'
    },
    initialize: function(){
      _.bindAll(this, 'render', 'addItem'); // every function that uses 'this' as the current object should be in here

      this.counter = 0; // total number of items added thus far
      this.render();
    },
    // `render()` now introduces a button to add a new list item.
    render: function(){
      $(this.el).append("<button id='add'>Add list item</button>");
      $(this.el).append("<ul></ul>");
    },
    // `addItem()`: Custom function called via `click` event above.
    addItem: function(){
      this.counter++;
      $('ul', this.el).append("<li>hello world"+this.counter+"</li>");
    }
  });

  var listView = new ListView();      
})(jQuery);

I don't understand why it has to be preceded by an (function($){....

Can anyone explain this to me?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

悟红尘 2025-01-01 06:37:31

这是创作 jQuery 插件时的常见做法。

原因是您希望避免与其他可能在全局范围内使用 $ 符号的库发生冲突。通过将代码包装在采用一个参数(名为 $)的函数调用中并将 jQuery 对象传递到该函数中,可以确保避免冲突。

function($) { // declare an anonymous function that takes an argument $

    // conflict safe code =)

}(jQuery); // pass the argument jQuery to the anonymous function

正如 nielsbot 指出的,如果给函数命名,可能会更容易看出上面代码的作用:

var executeSafely = function($) {

    // conflict safe code =)

}

executeSafely(jQuery);

我知道这一点这是事后的事情,但 MikeG 只是在这篇文章的评论中指出,这对于其他地方的 javascript 代码来说也不一定是坏事。我想我应该扩展一下原因:

范围界定的案例

假设您您的网站上有两个独立的 javascript 模块。假设您已在两个 js 文件 module-one.jsmodule-two.js 中编写了它们的代码。通常,页面上只有一个模块,因此在创作其中一个模块时,您并不关心另一个模块中发生的情况(甚至可能让不同的开发人员独立于另一个模块处理不同的模块)。

然后,您决定在起始页上显示这两个内容会很好,因此您在起始页 html 的 head 部分中包含以下内容:

<script type="text/javascript" src="module-one.js" />
<script type="text/javascript" src="module-two.js" />

[Cue:世界末日音乐!] 一切都崩溃了!到底发生了什么?

您查看模块的代码,并看到以下内容:

module-one.js:

var state = 0;

function init() {
    ...
}

etc...

module-two.js:

var state = 2;

function init() {
    ...
}

etc ...

这里发生了什么?

好吧,页面按顺序加载两个脚本 - 第一个 module-one.js 被加载,第一个模块的一切都进行了;然后,module-two.js 被加载,并且覆盖第一个模块中定义的一些变量!这是因为在 JavaScript 中在全局范围内定义一个变量,它被隐式地解释为在window 对象。因此,如果您依次运行这两个脚本文件,例如,您首先设置 window.state = 0,然后设置 window.state = 2。正如您所看到的,这些模块并不是真正独立的。例如,当加载两个脚本后调用 init() (或者实际上是 window.init())时,仅启动第二个模块 - 第一个模块init() 函数被覆盖(因为 window 只能有一个名为 init 的属性)并且不再存在。

范围界定来解决

这个问题 为了避免这个问题,您应该将模块包装在函数调用中,就像您对上面的 jQuery 插件所做的那样。但是,这些函数不需要接受任何参数:

module-one.js

(function() {
    // code for module one here
})();

module-two.js

(function() {
    // code for module two here
})();

现在,由于这两个模块是在单独的函数中定义的,因此所有变量的作用域仅限于这些函数内。如果您不确定如何使用 JavaScript 代码,将其包装在像这样的函数调用中是避免冲突的好习惯。而且,如果您不始终遵循良好的做法,就很难记住它们,因此始终遵循这一做法确实不会伤害任何人 =)

This is common practice when authoring jQuery plugins.

The reason is that you want to avoid conflicts with other libraries that may also use the $ symbol in the global scope. By wrapping your code in a function call that takes one argument (named $) and pass the jQuery object into that function, you ensure that you avoid conflicts.

function($) { // declare an anonymous function that takes an argument $

    // conflict safe code =)

}(jQuery); // pass the argument jQuery to the anonymous function

As nielsbot noted, it might be easier to see what the above code does if you give the function a name:

var executeSafely = function($) {

    // conflict safe code =)

}

executeSafely(jQuery);

I know this is way after the fact, but MikeG just pointed out in a comment on this post that this isn't necessarily a bad thing to do with javascript code in other places as well. I thought I'd expand a little on why:

A case for scoping

Suppose you have two independent javascript modules on your web site. Let's say you've written the code for them in the two js files module-one.js and module-two.js. Normally, you only have one module on a page, so when authoring one of them, you don't care what happens in the other one (you might even have different developers working on the different modules independently of the other).

Then, you decide it would be nice to show both these things on the start page, so you include the following in the head section of the start page html:

<script type="text/javascript" src="module-one.js" />
<script type="text/javascript" src="module-two.js" />

[Cue: Doomsday music!] Everything breaks down! What the heck happened?

You look in the code for the modules, and see the following:

module-one.js:

var state = 0;

function init() {
    ...
}

etc...

module-two.js:

var state = 2;

function init() {
    ...
}

etc ...

What's going on here?

Well, the page loads the two scripts in order - first module-one.js is loaded, and everything is go for the first module; then, module-two.js is loaded, and overrides some of the variables defined in the first module! This is because defining a variable in the global scope in JavaScript, it is implicitly interpreted as defining it on the window object. Thus, if you run the two script files after each other, you, for example, first set window.state = 0, and then window.state = 2. As you see, the modules aren't really independent. When, for example, init() (or, really, window.init()) is called after both scripts are loaded, only the second module is initiated - the first init() function was overwritten (since window can only have one property named init) and doesn't exist anymore.

Scoping to the rescue

To avoid this problem, you should wrap your modules in function calls, just like you did with the jQuery plugin above. However, these function don't need to take any arguments:

module-one.js

(function() {
    // code for module one here
})();

module-two.js

(function() {
    // code for module two here
})();

Now, since the two modules are defined inside separate functions, all variables are scoped to live only within those functions. If you're unsure how your JavaScript code will be used, wrapping it in a function call like this is good practice to avoid conflicts. And since it can be hard to remember good practices if you don't follow them all the time, following this one all the time really doesn't hurt anyone =)

眼泪都笑了 2025-01-01 06:37:31

这是为了保证 $ 被分配给定义函数内的 jQuery 对象。他们基本上是这样做的:

var theFunction = function($){...code...};
theFunction(jQuery);

你看到了吗?

It's to guarantee that $ is assigned to the jQuery object within the defined function. They're basically doing this:

var theFunction = function($){...code...};
theFunction(jQuery);

Do you see it?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文