JS编程建议——73:函数绑定有价值

建议73:函数绑定有价值
函数绑定就是为了纠正函数的执行上下文,特别是当函数中带有this关键字的时候,这一点尤其重要,稍微不小心,就会使函数的执行上下文发生跟预期不同的改变,导致代码执行上的错误。函数绑定具有3个特征:
函数绑定要创建一个函数,可以在特定环境中以指定参数调用另一个函数。
一个简单的bind()函数接收一个函数和一个环境,返回一个在给定环境中调用给定函数的函数,并且将所有参数原封不动地传递过去。
被绑定函数与普通函数相比有更多的开销,它们需要更多内存,同时也因为多重函数调用而稍微慢一点,最好只在必要时使用。
第一个特征常常和回调函数及事件处理函数一起使用。
var handler = {

message : 'Event handled',
handleClick : function(event) {
    alert(this.message);
}

};
var btn = document.getElementById('my-btn');
EventUtil.addHandler(btn, 'click', handler.handleClick); //undefined
出现上述结果的原因在于没有保存handler.handleClick()环境(上下文环境),所以this对象最后指向了DOM按钮而非handler。可以使用闭包修正此问题:
var handler = {

message : 'Event handled',
handleClick : function(event) {
    alert(this.message);
}

};
var btn = document.getElementById('my-btn');
EventUtil.addHandler(btn, "click", function(event) {

handler.handleClick(event);

});
这是特定于这段代码的解决方案。创建多个闭包可能会令代码变得难于理解和调试,因此,很多JavaScript库实现了一个可以将函数绑定到指定环境的函数bind()。
bind()函数的功能是提供一个可选的执行上下文传递给函数,并且在bind()函数内部返回一个函数,以纠正在函数调用上出现的执行上下文发生的变化。最容易出现的错误就是回调函数和事件处理程序一起使用。
function bind(fn, context) {

return function() {
    return fn.apply(context, arguments);
};

}
在bind()中创建一个闭包,该闭包使用apply调用传入的参数,并为apply传递context对象和参数。
注意:这里使用的arguments对象是内部函数的,而非bind()的。在调用返回的函数时,会在给定的环境中执行被传入的函数并给出所有参数。
var handler = {

message : 'Event handled',
handleClick : function(event) {
    alert(this.message);
}

};
var btn = document.getElementById('my-btn');
EventUtil.addHandler(btn, "click", bind(handler.handlerClick, handler));

时间: 2024-09-30 06:37:32

JS编程建议——73:函数绑定有价值的相关文章

JS编程建议——67:套用函数

建议67:套用函数套用是JavaScript函数一个很有趣的应用.所谓套用就是将函数与传递给它的参数相结合,产生一个新的函数.在函数式编程中,函数本身也是一个值,这种特性允许用户以有趣的方式去操作函数值.例如,在下面代码中定义一个add()函数,该函数能够返回一个新的函数,并把参数值传递给这个新函数,从而实现连加操作.var add = function(n){ return function(m){ return n+m; } }document.writeln(add(2)(3)); //5

JS编程建议——75:函数柯里化

建议75:函数柯里化柯里化是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回一个新函数,这个新函数能够接受原函数的参数.下面可以通过例子来帮助理解.function adder(num) { return function(x) { return num + x; } }var add5 = adder(5);var add6 = adder(6);print(add5(1)); // 6print(add6(1)); //7函数adder接受一个参数,并返回一个函数,这个返回的函数可

JS编程建议——22:少用函数迭代

建议22:少用函数迭代ECMA-262v4为本地数组对象新增加了一个forEach方法.此方法遍历一个数组的所有成员,并且在每个成员上执行一个函数.在每个元素上执行的函数作为forEach()的参数传进去,并在调用函数时接收3个参数:数组项的值.数组项的索引.数组自身.例如: items.forEach(function(value, index, array){ process(value); }); forEach在Firefox.Chrome和Safari等浏览器中为原生函数.另外,for

JS编程建议——37:推荐使用replace(1)

建议37:推荐使用replace(1)String对象的replace方法包含两个参数,第一个参数表示执行匹配的正则表达式,也可以传递字符串,第二个参数表示准备代替匹配的子字符串,例如,把字符串html替换为htm. var b = s.replace("html", "htm" ); 与search和match方法不同,replace方法不会把字符串转换为正则表达式对象,而是以字符串直接量的文本模式进行匹配.第二个参数可以是替换的文本,或者是生成替换文本的函数,把

JS编程建议——59:推荐动态调用函数

建议59:推荐动态调用函数调用函数更便捷的方式是使用Function对象的call和apply方法.apply与call方法在本质上没有太大区别,只不过它们传递给函数的参数方式不同, apply是以数组形式进行参数传递,而call方法可以同时传递多个值.如果某个函数仅能够接收多个参数列表,而现在希望把一个数组的所有元素作为参数进行传递,那么使用apply方法就显得非常便利.function max(){ var m = Number.NEGATIVE_INFINITY; // 声明一个负无穷大的

JS编程建议——74:使用高阶函数

建议74:使用高阶函数高阶函数作为函数式编程众多风格中的一项显著特征,经常被使用.实际上,高阶函数即对函数的进一步抽象.高阶函数至少满足下列条件之一:接受函数作为输入.输出一个函数. 在函数式语言中,函数不但是一种特殊的对象,还是一种类型,因此函数本身是一个可以传来传去的值.也就是说,某个函数在刚开始执行的时候,总可以送入一个函数的参数.传入的参数本身就是一个函数.当然,这个输入的函数相当于某个函数的另外一个函数.当函数执行完毕之后,又可以返回另外一个新的函数,这个返回函数取决于return f

JS编程建议——66:使用函数实现历史记录

建议66:使用函数实现历史记录函数可以利用对象去记住先前操作的结果,从而能避免无谓的运算,这种优化称为记忆.JavaScript的对象和数组要实现这种优化是非常方便的.例如,使用递归函数计算fibonacci数列.一个fibonacci数字是之前两个fibonacci数字之和.最前面的两个数字是0和1.var fibonacci = function(n) { return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); };for(var i

JS编程建议——72:惰性载入函数

建议72:惰性载入函数惰性载入函数主要解决的问题也是兼容性,原理跟分支函数类似,下面是简单的示例.var addEvent = function(el, type, handle) { addEvent = el.addEventListener ? function(el, type, handle) { el.addEventListener(type, handle, false); } : function(el, type, handle) { el.attachEvent("on&q

JS编程建议——71:推荐分支函数

建议71:推荐分支函数分支函数解决的一个问题是浏览器之间兼容性的重复判断.解决浏览器之间的兼容性的一般方式是使用if逻辑来进行特性检测或能力检测,根据浏览器不同的实现来实现功能上的兼容,这样做的问题是,每执行一次代码,可能都需要进行一次浏览器兼容性方面的检测,这是没有必要的.能否在代码初始化执行的时候就检测浏览器的兼容性,在之后的代码执行过程中,就无须再进行检测了呢?答案是:能.分支技术就可以解决这个问题,下面以声明一个XMLHttpRequest实例对象为例进行介绍.var XHR = fun