所以,几个月前我发现了一篇文章Essential jQuery Plugin Patterns。我试图编写一个简单的jQuery插件,我发现这篇文章非常有用。它包含大量信息,其中大部分信息超出了我对JavaScript或jQuery的专业知识。最感兴趣的是第一个插件模板,名为 jQuery Lightweight Plugin Boilerplate ,几个月前我在another question中引用了该模板。
最近,我开始使用CoffeeScript并查找 CoffeeScript jQuery插件模板,我找到了here。
这两者都实现了几乎相同的概念。这里有一些重要的不同之处是:
methods[method].apply this, Array::slice.call(arguments, 1)
做了什么,虽然我有点理解 Lightweight Boilerplate 的命名空间块。method.init()
中需要return $(this)
以及$(this).each()
。所以我继续拼接这两个。我写了自己的模板。在这里:
(($, window, document) ->
# ---------------------------------------------------------------------------
# Conventionally private variables
# ---------------------------------------------------------------------------
_PluginName = "FooBar"
_Defaults =
property: 'value' # etc. etc.
# ---------------------------------------------------------------------------
# Private methods
# ---------------------------------------------------------------------------
_Debug = (msg) ->
window.console.log(msg)
return
# ---------------------------------------------------------------------------
# Plugin Constructor
# ---------------------------------------------------------------------------
Plugin = (element, options) ->
@element = element
@options = $.extend true, {}, _Defaults, options
# TODO: Call methods to do stuff
return
# ---------------------------------------------------------------------------
# Plugin Methods
# ---------------------------------------------------------------------------
Plugin.prototype.init = () ->
# TODO: Plugin initializiation logic
return
Plugin.prototype.destroy = () ->
# TODO: Cleanup, unbind and eject
return
# ---------------------------------------------------------------------------
# Actual plugin body
# ---------------------------------------------------------------------------
$.fn[_PluginName] = (options) ->
return @.each () ->
($.data @, 'plugin_' + _PluginName
new Plugin @, options
) unless $.data @, 'plugin_' + _PluginName
return
) jQuery, window, document
我不是要求两个插件之间进行比较。而我的插件甚至还不完美。我从答案another question中发现,使用($, window, document)
闭包是一种矫枉过正的行为。可能还有其他错误,绝对欢迎您指出并讨论它们。
尽管如此,我还有一些非常具体的问题。
这些传统的“私人”对象/方法有多安全。如果有人故意打电话给Plugin()
而不是以正确的方式使用插件怎么办?可以在除此闭包之外的任何范围内访问_Defaults
吗?
这些“私人”物品的范围究竟是什么?它们是否会在jQuery名称空间中无所事事?他们会干涉什么吗?如何使用这些“私有”变量来帮助改善代码?
我不完全理解prototype
。 init()
本身的destroy()
和Plugin()
属性是?为什么init()
和destroy()
将options
的{{1}}属性称为Plugin()
,就好像this.options
和init()
在内部定义一样destroy()
本身的上下文......如果我将对象定义为Plugin()
怎么办? Plugin.prototype.methods
对象里面的函数this
是什么?
注意:如果任何人都难以关注链接以查看代码,请告诉我们。我将编辑此问题以包含代码。我没有包括因为那时问题会变得太长。
答案 0 :(得分:0)
当你做这样的事情时:
(->
Pancakes = ...
...
)()
JavaScript版本如下所示:
(function() {
var Pancakes;
Pancakes = ...
...
})();
特别是,Pancakes
是匿名自执行函数的本地,因此无法从函数外部访问它。另请注意,CoffeeScript编译器会将每个.coffee
文件包装在self-executing function to avoid scope creep中,即:
Pancakes = 6
最终为(或多或少):
(function() {
var Pancakes = 6;
})();
因此,即使您不手动添加某种范围包装器,CoffeeScript也会为您添加一个。当然,如果有人自己编译CoffeeScript,他们可以通过运行coffee --bare
来编译CoffeeScript来抑制外部函数包装器。 OTOH,每个人都有权使用脚枪,如果需要的话,欢迎他们自己射击。
应该回答 1 和 2 。
就你的原型问题而言,你应该写:
Plugin::init = -> ...
而不是直接引用prototype
,它们只是::
is more CoffeeScripty而是{。}}。
回到手头的问题。当你这样说:
class Pancakes
Pancakes::m = (where_is) -> 'house?'
与说法相同:
class Pancakes
m: (where_is) -> 'house?'
所以为prototype
分配内容只是在“类”中添加一个方法。这意味着@
(AKA this
)将(通常)成为对象:
pancakes = new Pancakes
pancakes.m() # `@` will be `pancakes` inside `m`
当然,任何CoffeeScript函数中@
的值取决于(就像在JavaScript中一样)函数的调用方式以及函数是否已绑定到对象。
您可以使用simple example验证这一点:
class C
constructor: ->
@p = Math.random()
console.log(@p)
C::m = -> console.log(@p)
(new C).m()
这将使您在控制台中获得与预期相同的随机数的两个副本。
希望能够处理 3 。