函数包装器在javascript中的重要性

时间:2009-12-19 00:23:54

标签: javascript function

有人可以向我解释使用函数包装器的重要性(即:在分配onclick功能时)吗?我知道我应该,但我不完全理解为什么......

实施例: 这是我的理解:

$(callingImg)[0].setAttribute("onclick", "function(){removeChildren(this);}");

比这更好:

$(callingImg)[0].setAttribute("onclick", "removeChildren(this)");

7 个答案:

答案 0 :(得分:12)

函数包装器最常见的用途之一是维护或锁定该函数的上下文。例如,如果你有一个对象,并且你想使用它的一个方法作为给定元素的onclick处理程序:

someElement.onclick = someObject.someMethod;

如果someObject.someMethodthis提及任何引用,而不是this指向someObject,则会指向someElement,因为上下文已更改。通过包装someObject.someMethod

someElement.onclick = function() { someObject.someMethod() };

您仍在执行someMethod作为someObject的方法,而不是someElement的方法。

但是,如果事件处理程序方法永远不会对this进行任何引用,则不需要包装器。

从您发布的示例代码中,如果您刚刚执行了

$(callingImg)[0].setAttribute("onclick", removeChildren(this));

removeChildren(this)将立即执行,其返回值将被指定为onclick处理程序。


以下是一些示例代码,用于说明正在发生的事情

var FakeElement = function() {
    this.name    = "FakeElement";
    this.onclick = function() {};
};

var FakeEventHandler = function() {
    this.name = "FakeHandlerObject";
    this.clickHandler = function() {
        console.log("`this` = ", this.name);
    };
};

var e = new FakeElement(); 
var h = new FakeEventHandler();

// Normal usage, `this` points to instance of `h`
console.info("h.clickHandler();");
h.clickHandler();

// Context of this is changed to `e` instead of `h`
console.info("e.onclick = h.clickHandler;");
e.onclick = h.clickHandler;
e.onclick();

// Wrapped to maintain proper context of `this` within `h`
console.info("e.onclick = function() { h.clickHandler(); };");
e.onclick = function() { h.clickHandler(); };
e.onclick();

// Executed immediately and returns `null` causing an error in `e.onclick();`
console.info("e.onclick = h.clickHandler();");
e.onclick = h.clickHandler();
e.onclick();

输出:

h.clickHandler();
`this` = FakeHandlerObject

e.onclick = h.clickHandler;
`this` = FakeElement

e.onclick = function() { h.clickHandler(); };
`this` = FakeHandlerObject

e.onclick = h.clickHandler();
`this` = FakeHandlerObject

作为旁注,看起来你正在使用jQuery。如果是这种情况,你可以简单地做

$($(callingImg)[0]).click(function() {
    removeChildren(this);
});

更好的是,如果总有一个callingImg或者你想对每个callingImg应用相同的点击处理程序,你可以做到

$(callingImg).click(function() {
    removeChildren(this);
});

答案 1 :(得分:1)

它们通常用于限制可变范围并保证您不会污染周围的范围。

答案 2 :(得分:1)

$(callingImg)[0].setAttribute("onclick", "function(){removeChildren(this);}");

这没有任何意义。它说:点击,定义一个功能,并不做任何事情。

$(callingImg)[0].setAttribute("onclick", "removeChildren(this)");

这将在IE上有效。 不要在HTML文档上使用setAttribute。 IE中的setAttribute存在许多错误,影响各种属性,包括所有事件处理程序。一般而言,setAttribute与更简单,更易于阅读的DOM Level 1 HTML属性相比没有优势。

它也是从字符串中定义代码,这被广泛认为是不好的做法。如果您开始将变量放入字符串中,它会变得更慢,容易出现安全问题,并且在将来可能会破坏内容安全实践。

通常,您使用函数文字:

$(callingImg)[0].onclick= function() {
    removeChildren(this);
};

然而$看起来你正在使用jQuery,在这种情况下你应该使用jQuery自己的事件处理东西:

$(callingImg).click(function() {
    removeChildren(this);
});

答案 3 :(得分:1)

应该使用一组非常简单的包装函数来隔离文档对象模型(DOM)和应用程序javascript。通过这样做,您可以完成许多事情,即1)您将逻辑与用户代理分开,从而获得浏览器的交叉兼容性,以及2)您在项目中节省了大量代码。例如,问问自己有多少次你引用了“document.getElementById()”函数?

为什么不按如下方式创建函数:

函数GE(s){return document.getElementById(s);}

现在,在整个javascript代码中,包括HTML(内联)中包含的代码,您可以更改对新函数的引用,删除一堆代码。

如果W3C更改了document.getElementById函数的功能访问点,您只需在一个位置更改它。

此外,现在您可以将错误捕获和使用计数添加到GE()函数中。

可以对document.createElement()函数执行相同的操作。

function CE(tag){return document.createElement(tag);}

在许多应用程序中,第一步应该是以这种方式隔离DOM,为每个要使用的DOM级别函数创建一个“包装器”函数。

我希望这会有所帮助。

答案 4 :(得分:0)

所以你可以重复使用这些功能。

或许可以更详细地解释为什么你不清楚,我很乐意帮助解释。

答案 5 :(得分:0)

在这种情况下,函数包装器的一些用途是,您可以在单个事件中执行多个语句,这样您就可以更好地控制传入的参数。

如果没有必需的参数,只需在事件绑定中输入要调用的函数的名称即可。否则,您可以将内联函数(){}放入要执行的空间中。我认为没有理由把它作为一个字符串放在元素的属性中。就像你做的那样。

W / jQuery的

$( callingImg ).click( aFunctionPointer );
// or if you need arguments
$( callingImg ).click( function( ){ aFunction( someArg ); } );

W /原型

Event.observe( callingImg, 'click', aFunctionPointer );
// or if you need arguments
Event.observe( callingImg, 'click', function( ){ aFunction( someArg ); } );

请勿混用和匹配这些方式,例如

$( callingImg ).click( aFunction( ) ); // DON'T DO IT

因为它将执行aFunction()并将使用任何返回值(当然,除非你返回一个函数,但我怀疑它)作为click事件。

答案 6 :(得分:-1)

实际上它应该是

$(callingImg)[0].setAttribute("onclick", function(){removeChildren(this);});

$(callingImg)[0].setAttribute("onclick", "removeChildren(this)");

首先是内联定义的匿名函数,将在事件触发后调用,第二个是需要eval'编辑的字符串,这是较慢和邪恶的。