javascript 在包装 jQuery 插件的匿名函数中使用“window”、“document”和“undefined”作为参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15777519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using 'window', 'document' and 'undefined' as arguments in anonymous function that wraps a jQuery plugin
提问by Zia Ur Rehman
Honestly, I didn't know how to make the title shorter.
老实说,我不知道如何缩短标题。
I learnt how to write a jQuery plugin by studying the source of SlidesJSplugin. When I encountered something new, I just asked my good friend Googleand most of the times, got a satisfactory answer. Honestly though, I never made much effort. All I know is that $
is (probably) a shorthand jQuery object constructor and that $()
and jQuery()
are the same thing provided jQuery is included.
通过研究SlidesJS插件的源码,我学会了如何编写jQuery插件。当我遇到新的东西时,我只是问我的好朋友谷歌,大多数时候,得到了满意的答案。老实说,我从来没有付出太多努力。我所知道的$
是(可能)是一个简写的 jQuery 对象构造函数,$()
并且jQuery()
如果包含 jQuery,那么它是相同的。
Recently, though, I tried to understand the science behind jQuery and how to write a goodjQuery plugin. I came across a very good articlein which the author listed several templatesfor creating a jQuery plugin. Since the rest were too complex for me to understand, I liked the first one: A Lightweight Start. Now, here is the code for the said template.
不过,最近我试图了解 jQuery 背后的科学以及如何编写一个好的jQuery 插件。我看到了一篇很好的文章,其中作者列出了几个用于创建 jQuery 插件的模板。由于其余的太复杂了,我无法理解,我喜欢第一个:轻量级开始。现在,这是上述模板的代码。
/*!
* jQuery lightweight plugin boilerplate
* Original author: @ajpiano
* Further changes, comments: @addyosmani
* Licensed under the MIT license
*/
// the semi-colon before the function invocation is a safety
// net against concatenated scripts and/or other plugins
// that are not closed properly.
;(function ( $, window, document, undefined ) {
// undefined is used here as the undefined global
// variable in ECMAScript 3 and is mutable (i.e. it can
// be changed by someone else). undefined isn't really
// being passed in so we can ensure that its value is
// truly undefined. In ES5, undefined can no longer be
// modified.
// window and document are passed through as local
// variables rather than as globals, because this (slightly)
// quickens the resolution process and can be more
// efficiently minified (especially when both are
// regularly referenced in your plugin).
// Create the defaults once
var pluginName = 'defaultPluginName',
defaults = {
propertyName: "value"
};
// The actual plugin constructor
function Plugin( element, options ) {
this.element = element;
// jQuery has an extend method that merges the
// contents of two or more objects, storing the
// result in the first object. The first object
// is generally empty because we don't want to alter
// the default options for future instances of the plugin
this.options = $.extend( {}, defaults, options) ;
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype.init = function () {
// Place initialization logic here
// You already have access to the DOM element and
// the options via the instance, e.g. this.element
// and this.options
};
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName,
new Plugin( this, options ));
}
});
}
})( jQuery, window, document );
I have included the comments so as to refer to them in my questions.
我已经包含了这些评论,以便在我的问题中引用它们。
I have a crude idea why window
and document
have been included in the argument of the anonymous function that wraps the plugin (I don't know what else to call it)because it is given in the comments that it sorta kinda shortens the execution time. But how does that work? Any argument of the said anonymous function wrapping the plugin gets passed on to where? And how are these addressed in the plugin?
我有一个粗略的想法,为什么window
并且document
已经包含在包装插件的匿名函数的参数中(我不知道还能叫它什么),因为它在评论中给出,它有点缩短了执行时间。但这如何运作?包装插件的上述匿名函数的任何参数都会传递到哪里?以及如何在插件中解决这些问题?
Normally, I would do $(window).resize(function(){})
but that doesn't work in this case. If I do console.log(window)
inside the Plugin function, it says 'undefined'.
通常,我会这样做,$(window).resize(function(){})
但在这种情况下不起作用。如果我console.log(window)
在 Plugin 函数内部执行,它会显示“未定义”。
Which brings me to the other question which is: what is undefined? Isn't it a data typethat is assigned to an objectthat isn't defined in the scope? How can it be passed as an argument? Don't the arguments have to be objects? There are a few lines written about this in the comments, but I don't understand a word of it: <so we can ensure that its value is truly undefined> whaaa?
这让我想到了另一个问题:什么是undefined?它不是分配给范围中未定义的对象的数据类型吗?如何将其作为参数传递?参数不是必须是对象吗?评论中有几行是关于这个的,但我一个字都没看懂:<所以我们可以确保它的值是真正未定义的> whaaa?
To sum up:
总结:
- What indeed is meant by
function($)
? - Why should I include
window
,document
andundefined
as arguments offunction($)
? - If I do it, how do I access the actual
window
anddocument
objects? undefined
what, and why?
- 究竟是什么意思
function($)
? - 为什么要包括
window
,document
和undefined
作为 的参数function($)
? - 如果我这样做,我如何访问实际
window
和document
对象? undefined
什么,为什么?
Please go easy on me. I never studied programming language as a subject for the express purpose of writing applications. I studied basic C for writing hardware oriented low-level routines for tiny core microcontrollers and that's just about it. I did learn C++ extensively and a bit of Java on my own. Just so you'd know what to expect.
请放过我吧。我从来没有为了编写应用程序而将编程语言作为一门学科来学习。我学习了基本的 C 语言,用于为微型核心微控制器编写面向硬件的低级例程,仅此而已。我确实广泛地学习了 C++,并自己学习了一些 Java。只是为了让你知道会发生什么。
采纳答案by bchociej
When you write a function like:
当您编写如下函数时:
(function (foo, bar) {
return foo.getElementById(bar);
})(document, "myElement")
then the function is immediately called with arguments document
and "myElement"
for parameters foo
and bar
. Therefore, inside the function, foo.getElementById(bar)
is equivalent to document.getElementById("myElement")
.
然后立即使用参数document
和"myElement"
参数调用该函数foo
和bar
。因此,在函数内部,foo.getElementById(bar)
等价于document.getElementById("myElement")
。
Similarly, in your plugin example, you are immediately calling the function with the arguments jQuery, document, window
.
同样,在您的插件示例中,您立即使用参数调用函数jQuery, document, window
。
What indeed is meant by
function($)
?
究竟是什么意思
function($)
?
The $
simply represents a reference to a jQuery
object that is passed in to the wrapper function. Later, when the anonymous function is called with (jQuery, window, document)
, the $
reference inside the function references the jQuery
object. This is done for a number of reasons, not least of which is that $
is quicker to type. It also allows the user to apply your plugin in wrapper to a particular instanceof jQuery
, produced perhaps by jQuery.noConflict()
.
在$
仅表示一个基准jQuery
是在所述包装函数传递的对象。后来,当匿名函数被调用时(jQuery, window, document)
,$
函数内部的引用引用了jQuery
对象。这样做的原因有很多,其中最重要的是$
键入速度更快。它还允许在包装应用插件的用户特定实例的jQuery
,由生产可能jQuery.noConflict()
。
Why should I include
window
,document
andundefined
as arguments offunction($)
?
为什么要包括
window
,document
和undefined
作为 的参数function($)
?
You don't needto include these. The original author's reasoning is that assigning function-local variables to reference these will shorten the time it takes to resolve these variables. I assert that the savings are negligible; I personally wouldn't bother unless I used a lotof references to window
and/or document
.
您不需要包含这些。原作者的推理是,将函数局部变量赋值给引用这些会缩短解析这些变量的时间。我断言节省的钱可以忽略不计;我个人不会打扰,除非我使用了很多对window
和/或document
.
As for undefined
, the original author's purpose in including this is to ensure that someone hasn't altered the undefined
global variable in EcmaScript 4 (edit: actually ECMAScript 3 -- version 4 never made it) or earlier. Again, I can't envision this problem cropping up. If you're truly worried that this could be a problem, just include something like this in your function:
至于undefined
,原始作者包含此内容的目的是确保有人没有更改undefined
EcmaScript 4(编辑:实际上 ECMAScript 3 - 版本 4 从未做过)或更早版本中的全局变量。同样,我无法想象这个问题会突然出现。如果您真的担心这可能是一个问题,只需在您的函数中包含以下内容:
if(typeof undefined !== "undefined") {
undefined = void 0;
}
If I do it, how do I access the actual
window
anddocument
objects?
如果我这样做,我如何访问实际
window
和document
对象?
All you have to do is make sure that the function call at the end of your anonymous function passes in the actual (jQuery, window, document) parameters. Or, don't include the window
and document
arguments in your function signature. Either way, you will be referring to the actualobjects, regardless of the level of indirection.
您所要做的就是确保匿名函数末尾的函数调用传递了实际的(jQuery、窗口、文档)参数。或者,不要在函数签名中包含window
和document
参数。无论哪种方式,您都将引用实际对象,而不管间接级别如何。
undefined
what, and why?
undefined
什么,为什么?
undefined
is a global variable of type "undefined". Fields that have not been initialized are exactly equal (===) to undefined. It allows the programmer to differentiate between a deliberately null value and a simple uninitialized one. In ECMAScript 5 and later, undefined
is read only. Prior to that, it is possible that other code could modify the value of undefined
. You can alwaysget the true value undefined
with the expression void 0
... as in myUndefinedVar = void 0;
.
undefined
是一个“未定义”类型的全局变量。尚未初始化的字段完全等于 (===) 为 undefined。它允许程序员区分故意为空值和简单的未初始化值。在 ECMAScript 5 及更高版本中,undefined
是只读的。在此之前,其他代码可能会修改 的值undefined
。你总是可以undefined
用表达式得到真正的值void 0
... 如myUndefinedVar = void 0;
。
回答by Sunyatasattva
What is meant by
function($)
?
是什么意思
function($)
?
Passing $
as an argument to your function makes it possible for you to use the jQuery
shorthand object, which, as you clearly identified, is just an alias of the jQuery
object (also take a look at jQuery.noConflict()
).
$
作为参数传递给您的函数使您可以使用jQuery
速记对象,正如您明确指出的那样,它只是jQuery
对象的别名(另请参阅jQuery.noConflict()
)。
Why should I include
window
,document
andundefined
as arguments offunction($)
? I have a crude idea why window and document have been included in the argument of the anonymous function that wraps the plugin (I don't know what else to call it) because it is given in the comments that it sorta kinda shortens the execution time. But how does that work? Any argument of the said anonymous function wrapping the plugin gets passed on to where?
为什么要包括
window
,document
和undefined
作为 的参数function($)
?我有一个粗略的想法,为什么窗口和文档已包含在包装插件的匿名函数的参数中(我不知道还能调用什么),因为它在评论中给出,它有点缩短了执行时间. 但这如何运作?包装插件的上述匿名函数的任何参数都会传递到哪里?
Passing window
and document
as local variables kinda shortens the execution timebecause it is easier and faster to access a local variable than a global variable, because local variables are first in the chain. Which sort of answers your second question: the arguments get passed inside the anonymous function scope, which is the whole point of you making an anonymous function anyways: to create a closure.
传递window
和document
作为局部变量有点缩短了执行时间,因为访问局部变量比访问全局变量更容易、更快,因为局部变量在链中是第一个。哪种回答你的第二个问题:参数在匿名函数范围内传递,这就是你制作匿名函数的重点:创建一个闭包。
Those arguments are passed at the end of your function, where you see the last parenthesis. The variable window
in your closure refers to the global window
because you passed it at the end.
这些参数在函数的末尾传递,在那里您可以看到最后一个括号。window
闭包中的变量指的是 ,global window
因为你最后通过了它。
The reason why you pass undefined
is because undefined
is a Javascript confusing mess. Basically, undefined
is a property of the global object, that is, it is a variable, a singleton. It is not protected, that means that can be overridden. It means you could have an undefined
which is actually defined.
你通过的原因undefined
是因为undefined
是一个 Javascript 混乱的混乱。基本上,undefined
是全局对象的一个属性,也就是说,它是一个变量,一个单例。它不受保护,这意味着可以覆盖。这意味着你可以有一个undefined
实际定义的。
By passing undefined
you make sure that, even if anyone messed with undefined
in the global scope (never trust the global scope! :)), you still get a correct undefined
.
通过传递,undefined
您可以确保,即使有人undefined
在全局范围内搞砸了(永远不要相信全局范围!:)),您仍然会得到正确的undefined
.
Also, the same performance reasons apply to undefined
.
此外,相同的性能原因也适用于undefined
.
If I do it, how do I access the actual window and document objects?
如果我这样做,我如何访问实际的窗口和文档对象?
You are already accessing them, because you are passing them to your function. And as such you are able to manipulate them.
您已经在访问它们,因为您正在将它们传递给您的函数。因此,您可以操纵它们。
回答by slebetman
Before answering in detail let me note that unlike other programming languages, javascript is a bit odd for two reasons: first, it was created in haste this meant lots of things didn't get refined or implemented well. Second it was adopted by the internet very, very quickly and Microsoft copied the language very quickly and very accurately (including the bugs in the language). The result of this is that trying to correct mistakes in the design of the language was hard and/or impossible because they didn't want to break compatibility with existing websites.
在详细回答之前,让我指出,与其他编程语言不同,javascript 有点奇怪,原因有两个:首先,它是匆忙创建的,这意味着很多东西没有得到完善或实施。其次,它非常非常快地被互联网采用,微软非常迅速和非常准确地复制了该语言(包括语言中的错误)。这样做的结果是,试图纠正语言设计中的错误是困难的和/或不可能的,因为他们不想破坏与现有网站的兼容性。
Now to go into the details:
现在进入细节:
What indeed is meant by function($)
function($) 的真正含义是什么
Nothing special. In javascript function and variable names are allowed to use the letters a-z
including uppercase, the numbers 0-9
and the symbols $
and _
. There are no other restrictions on how they can be used. Though there are guidelines and conventions, some mentioned by the language spec itself, some grew with the programming community.
没什么特别的。在javascript函数和变量名中允许使用字母,a-z
包括大写、数字0-9
和符号$
和_
。它们的使用方式没有其他限制。虽然有一些指导方针和约定,有些是语言规范本身提到的,有些是随着编程社区的发展而增长的。
Therefore, $
is just a variable name. There is no difference between:
因此,$
只是一个变量名。之间没有区别:
function foo ($) {alert($)}
and
和
function foo (x) {alert(x)}
It's just the name chosen for the parameter. However, the spec strongly suggests that $
shouldn't be used by code written by humans. It's ok for computer generated code (a coffeescript compiler for example) but not ok for regular scripts. On the other hand it is strongly encouraged in scripts that use jQuery that $
always refer to the jQuery object (which incidentally happens to also be a function, that's fine in javascript since functions are objects).
它只是为参数选择的名称。但是,规范强烈建议$
不应由人类编写的代码使用。它适用于计算机生成的代码(例如一个 coffeescript 编译器),但不适用于常规脚本。另一方面,在使用 jQuery 的脚本中强烈鼓励它$
总是引用 jQuery 对象(顺便说一下,它也是一个函数,这在 javascript 中很好,因为函数是对象)。
Since you're writing jQuery the meaning of function ($)
is an anonymous function that accepts one argument and the argument it expects is a jQuery object.
由于您正在编写 jQuery,因此它的含义function ($)
是一个匿名函数,它接受一个参数,而它期望的参数是一个 jQuery 对象。
Why should I include window, document and undefined as arguments of function($)?
为什么要包含 window、document 和 undefined 作为函数($)的参数?
Arguably, one of the design mistakes in javascript is the lack of support for constants and/or immutable/protected variables/objects. As such, window
, document
and undefined
are actually regular global variables - anyone can reassign them to anything.
可以说,javascript 中的设计错误之一是缺乏对常量和/或不可变/受保护变量/对象的支持。因此,window
,document
和undefined
实际上是常规的全局变量 - 任何人都可以将它们重新分配给任何东西。
The following is crazy but valid javascript code:
以下是疯狂但有效的 javascript 代码:
window = 42;
No sane programmer would do this but it's possible none the less. The jQuery developers were very concerned by this and so jQuery tries its best to pass the real window
, document
and undefined
into plugins in case anyone is crazy enough to do crazy things.
没有理智的程序员会这样做,但仍然有可能。jQuery 开发人员对此非常关注,因此 jQuery 尽最大努力将真实的window
,document
和undefined
插件传递给插件,以防有人疯狂到做疯狂的事情。
One of the features of javascript is that function arguments override global variables. So if any of the above variables have been hiHymaned by someone else they are reassigned to their proper names in the function.
javascript 的特性之一是函数参数覆盖全局变量。因此,如果上述任何变量被其他人劫持,它们将在函数中重新分配给它们的专有名称。
If I do it, how do I access the actual window and document objects?
如果我这样做,我如何访问实际的窗口和文档对象?
You are expected to pass the correct window
, document
and undefined
as arguments named window
, document
and undefined
into the function. Doing anything else means that you no longer have access to the window
, document
and undefined
objects.
您应该将正确的window
, document
andundefined
作为名为window
, document
and 的参数传递undefined
到函数中。做其他任何事情都意味着您无法再访问window
,document
和undefined
对象。
There are crazy workarounds that you can do to try go grab a hold of the window
object (also know as the global object) and from there you can get a hold of document
. The jQuery code is actually one workaround to get back undefined
in case it has been hiHymaned.
您可以采取一些疯狂的解决方法来尝试抓住window
对象(也称为全局对象),然后从那里获取document
. jQuery 代码实际上是一种解决方法,可以undefined
在它被劫持时恢复。
undefined what, and why?
未定义什么,为什么?
As you correctly stated. undefined
is the value javascript gives to things that are declared but have no values assigned to them. But in javascript undefined
is just a global variable. If you don't touch it it initially has the value of undefined
(circular logic, I know). But it can be modified:
正如你所说的那样。undefined
是 javascript 赋予已声明但未分配任何值的事物的值。但在 javascriptundefined
中只是一个全局变量。如果你不碰它,它最初的价值是undefined
(我知道是循环逻辑)。但是可以修改:
undefined = 'boom!';
And henceforth all undefined variables will have the value of "boom!"
. The latest spec of the javascript language actually disallows reassigning to undefined but as of today only Safari does this.
从此以后,所有未定义的变量都将具有 值"boom!"
。javascript 语言的最新规范实际上不允许重新分配给 undefined 但截至今天,只有 Safari 这样做。
Again, no sane programmer will do this.
同样,没有理智的程序员会这样做。
回答by RobG
The inclusion of an identifier in a parameter list is effectively the same as declaring the variable in the function body, e.g.
在参数列表中包含标识符实际上与在函数体中声明变量相同,例如
function bar(foo) {
}
is equivalent to
相当于
function bar(foo) {
var foo;
}
but of course you just do the first if you want to pass a value to foo.
但当然,如果您想将值传递给foo,您只需执行第一个。
The primary reason for doing:
这样做的主要原因:
(function($) {
// use $ here instead of jQuery
}(jQuery));
is that when jQuery was released, Prototype.js had already been using "$" as an identifier for its main function for some time. The above pattern allows jQuery and prototype.js to be used in the same page, using "$" as an identifier for different things.
是在 jQuery 发布时,Prototype.js 已经使用“$”作为其主要功能的标识符有一段时间了。上面的模式允许在同一个页面中使用 jQuery 和prototype.js,使用“$”作为不同事物的标识符。
Passing in documentand windowis, at best, a micro optimisation that has little benefit. It offers no protection against them being assigned different values than expected. Just don't bother and use windowand documentinside the function as global identifiers.
传入文档和窗口充其量只是一种微优化,几乎没有什么好处。它无法防止它们被分配与预期不同的值。只是不要打扰并在函数内使用window和document作为全局标识符。
Including undefinedin the parameters and not passing it a value is not a sensible way of ensuring undefinedreally is undefined as it can still be affected if a value is accidentally passed. A safer way is:
在参数中包含undefined并且不向它传递值并不是确保undefined真的是 undefined的明智方法,因为如果一个值被意外传递,它仍然会受到影响。更安全的方法是:
(function() {
var undefined;
...
}());
Now you are certainthat undefinedin the scope of the function really is undefined. Or if you want an assignment:
现在你一定是未定义的功能确实是不确定的范围。或者如果你想要一个任务:
(function() {
var undefined = void 0;
...
}());
But that is just extra typing.
但这只是额外的打字。