假设我有以下jQuery代码:
var FooBar = {
zizzle: function (callback) {
var x, y, z;
// … do stuff with x y and z
callback(z, y, z);
}
}
$("a[href]").each(function () {
var link = this;
// do things with the link, e.g.
$(link).data('fiddle', "deedee")
function do_something() {
console.log("I would use the link variable here:", link)
// lots of code here using link
// blah, blah, blah link
}
$(this).click(function () {
FooBar.zizzle(do_something);
});
});
目前,由于do_something
位于定义link
的函数内部,因此它可以访问该变量(闭包)。但是,我想知道是否可以避免为每个链接创建函数。我宁愿做更接近这件事的事情:
var FooBar = {
zizzle: function (callback) {
var x, y, z;
// … do stuff with x y and z
callback(z, y, z);
}
}
function do_something() {
console.log("I would use the link variable here:", link)
// lots of code here using link
// blah, blah, blah link
}
$("a[href]").each(function () {
var link = this;
// do things with the link, e.g.
$(link).data('fiddle', "deedee")
$(this).click(function () {
FooBar.zizzle(do_something);
});
});
这样do_something
只创建一次。但是,如果我执行此操作,则do_something
不再具有link
的值。
在这种情况下假设无法更改FooBar
的代码,并且它只需要回调并且无法发送任何其他参数。
我想到的唯一选择就是这样,至少只根据需要创建函数:
var FooBar = {
zizzle: function (callback) {
var x, y, z;
// … do stuff with x y and z
callback(z, y, z);
}
}
function do_something_maker(link) {
return function (x, y, z) {
console.log("I would use the link variable here:", link)
// lots of code here using link
// blah, blah, blah link
}
}
$("a[href]").each(function () {
var link = this;
// do things with the link, e.g.
$(link).data('fiddle', "deedee")
$(this).click(function () {
FooBar.zizzle(do_something_maker(link));
});
});
这是最好的选择吗?
答案 0 :(得分:2)
你走了:
var FooBar = {
zizzle: function (callback) {
var x, y, z;
// … do stuff with x y and z
callback(z, y, z);
}
}
function do_something() {
console.log("I would use the link variable here:", do_something.link);
//if no link exists, abort
if(!do_something.link){return;}
//code with do_something.link
//you might want to delete afterwards
//delete do_something.link;
}
$("a[href]").click(function () {
do_something.link = this;
FooBar.zizzle(do_something);
});
如果你有异步和缓慢进行的事情,你可以尝试让它像do_something_maker或bind / $。代理方法一样懒,但每个链接只有一次(在第一次点击时将其添加到$ .data)
var FooBar = {
zizzle: function (callback) {
var x, y, z;
// … do stuff with x y and z
callback(z, y, z);
}
}
function do_something() {
console.log("I would use the link variable here:", this);
}
$("a[href]").click(function () {
var fn = $.data(this, 'zizzleCB') || $.data(this, 'zizzleCB', do_something.bind(this));
FooBar.zizzle(fn);
});
答案 1 :(得分:0)
为什么不直接将“link”作为参数传递给zizzle函数并将其传递给回调?
喜欢:
var FooBar = {
zizzle: function (callback,link) {
var x, y, z;
// … do stuff with x y and z
callback(x, y, z, link);
}
}
function do_something(x, y, z, link) {
console.log("I would use the link variable here:", link)
// lots of code here using link
// blah, blah, blah link
}
$("a[href]").on("click", function () {
FooBar.zizzle(do_something, this);
});
答案 2 :(得分:0)
只是为了踢:
var Util = function() {};
Util.prototype.do_something = function() {};
var FooBar = function() {
};
FooBar.prototype.zizzle = function(fn) {};
var fooBar = new FooBar();
var util = new Util();
fooBar.zizzle(util.do_something);
这给了你什么?
对于您创建的每个FooBar
对象,您将减少1个zizzle
的实例(因为所有函数都是实际上少了1个的对象)。
对于Util
的每个实例,您将减少1个do_something
的实例
并且您现在可以更好地决定何时需要Util
实例,而不是使用未使用的函数使全局对象混乱。
这是有效的,因为我们在原型上定义了一个函数,而不是让函数在对象文字{}
中猖獗或将它们附加到全局命名空间
答案 3 :(得分:0)
您可以使用Function.prototype.bind:
var FooBar = {
zizzle: function (callback) {
var x, y, z;
// … do stuff with x y and z
callback(z, y, z);
}
}
function do_something() {
console.log("'this' refers to link here", this)
// lots of code here using link
// blah, blah, blah link
}
$("a[href]").each(function () {
link = this;
$(this).click(function () {
FooBar.zizzle(do_something.bind(link));
});
});
答案 4 :(得分:0)
您应该注册点击您感兴趣的元素的容器。在您的情况下,这将是document.body。然后有一个额外的选择器找出何时采取行动:http://api.jquery.com/on/这是一个例子
function create_do_something($link){
return function(z,y,x){
do_something(z,y,x);
};
}
$(document.body).on("click","a[href]",function () {
var $link = this;
FooBar.zizzle(create_do_something($link));
});
刚发现一些东西,如果你有任何使用$("a[href]").click
或$("a[href]").on
的解决方案,jQuery将为选择器中的每个找到的元素创建一个闭包。
在Chrome中运行一些测试并执行堆快照会产生以下结果:
没有jQuery,也没有JS代码:
2557次关闭
根本没有代码(只是jQuery和jQuery ui):
5832关闭
使用以下代码
$(document.body).on("click","div"
,function(){console.log("hi");});
5834次关闭(有2个div)
5834个闭包(100个div),注意闭包的数量保持不变
使用以下代码
$("div").click(function(){console.log("hi");});
5835次关闭(有2个div)
5933个闭包(100个div),注意有98个闭包更多,所以jQuery为你在选择器中的每个找到的元素添加一个闭包。
那么为什么$("div").click
有更多的闭包呢?
jQuery 1.10.2在第4762行未经证实:
eventHandle = elemData.handle = function( e ) {
当你设置一个断点时,你会看到jQuery为选择器中找到的每个元素添加一个闭包。所以$(“div”)返回了100,$(document.body)有一个,无论有多少div。