我相信这个问题与此有关:How does the init function work in plugins?无论谁能回答这个问题,都可以回答这个问题。
我注意到jQuery的一些内容,如果我将我的插件称为:
$('.view_title_images').prodigal({width: 500});
$('.glglg').prodigal({ width: 600 });
然后,在我的init
函数中,我延伸:
options = $.extend({}, options, opts);
并将其添加到选择器中的每个元素:$(this).data('prodigal', options)
。当我在{{1}上调用另一个函数width
时,我会得到每个元素的正确500
值(一个600
和另一个open
)元素。
但是,如果我这样做:
click
对于两个选择器,尽管被单独调用,但我得到options = $.extend(options, opts);
。我在600
函数中执行此操作:
open
我知道不扩展到空对象会覆盖该选择器/全局对象的对象,但为什么会在每个选择器的console.log($(this).data('prodigal'));
上发生这种情况?
答案 0 :(得分:1)
首先,它是一个对象,而不是一个数组。并且您很可能不想扩展预先存在的对象,而是创建一个基于默认值的新对象,然后使用传递的选项覆盖那些,如下所示:
options = $.extend({}, defaults, opts);
$.extend
所做的是它将使用其余参数扩展第一个参数(数组或对象)。将预先存在的对象作为第一个参数传递将不会创建克隆,而是更改原始对象。
在上面的示例中,通过传递一个新对象({}
),我们改为创建第二个参数的克隆,然后我们用第三个参数覆盖。
更改此内容会解决很多问题,但您仍然可以遇到竞争条件,因为它仍然会在实例之间共享相同的选项对象。那么,如果我只想改变其中一个或两个实例的选项呢?
解决方案很简单,只需将该行移到.each
循环中,插件的每个实例都有自己的选项对象。
答案 1 :(得分:0)
即使@Marcus的答案很好,它显示了一个很好的插件设置,实际上可以避免这种混乱,我想我会把这个答案放在一边,因为它只是更好地回答了这个问题。
我正在见证,就像在PHP中一样,这里有关于内存管理的写入方案的副本:What is copy-on-write?我的init函数,如此小提琴中显示的那样:http://jsfiddle.net/Sammaye/65XLy/1会受到被引用的静态选项对象的影响每个电话。所以两者:
$('.view_title_images').prodigal({width: 500});
$('.glglg').prodigal({ width: 600 });
在内存中为插件中的options
对象引用相同的位置,因为数据赋值不是写入安全的副本:
$(this).data('prodigal', options).on('click', open);
这证明是因为如果你在小提琴中改变这一行:
$(this).data('prodigal', $.extend(options, opts)).on('click', open);
它实际上与var options = $.extend({}, options, opts);
的作用相同,它会复制到扩展上的新空对象,在写入时复制会触发副本。
这就是我看到这个的原因,因为每个元素中的data
实际上是对静态对象(插件)options
对象的引用。
作为补充说明,我在发布此答案后很快就发现了这一点:http://my.opera.com/GreyWyvern/blog/show.dml/1725165作者声明:
有一些事情可以让人们了解Javascript。一个事实是,为变量分配布尔值或字符串会生成该值的副本,而将数组或对象分配给变量则会引用该值。
这完全解释了我的问题。