Skip to content

Commit c9d0b29

Browse files
committed
函数绑定
1 parent e95b04f commit c9d0b29

2 files changed

Lines changed: 183 additions & 6 deletions

File tree

JS高级技巧/高级函数.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,128 @@ createXHR运行之后,会被重新改写了,之后的createXHR是改写后
274274

275275
函数绑定要创建一个函数,可以在特定的 this 环境中以指定参数调用另一个函数。该技巧常常和回调函数与事件处理程序一起使用,以便在将函数作为变量传递的同时保留代码执行环境。
276276

277+
<script>
278+
//这里是事件工具库;
279+
var EventUtil = {
280+
addHandler: function (element, type, handler) {
281+
if (element.addEventListener) {
282+
element.addEventListener(type, handler, false);
283+
} else if (element.attachEvent) {
284+
element.attachEvent("on" + type, handler);
285+
} else {
286+
element["on" + type] = handler;
287+
}
288+
},
289+
removeHandler: function (element, type, handler) {
290+
if (element.removeEventListener) {
291+
element.removeEventListener(type, handler, false);
292+
} else if (element.detachEvent) {
293+
element.detachEvent("on" + type, handler);
294+
} else {
295+
element["on" + type] = null;
296+
}
297+
},
298+
299+
getEvent: function (event) {
300+
return event ? event : window.event;
301+
},
302+
getTarget: function (event) {
303+
return event.target || event.srcElement;
304+
},
305+
preventDefault: function (event) {
306+
if (event.preventDefault) {
307+
event.preventDefault();
308+
} else {
309+
event.returnValue = false;
310+
}
311+
},
312+
stopPropagation: function (event) {
313+
if (event.stopPropagation) {
314+
event.stopPropagation();
315+
} else {
316+
event.cancelBubbles = true;
317+
}
318+
},
319+
getRelatedTarget: function (event) {
320+
if (event.relatedTarger) {
321+
return event.relatedTarget;
322+
} else if (event.toElement) {
323+
return event.toElement;
324+
} else if (event.fromElement) {
325+
return event.fromElement;
326+
} else { return null; }
327+
328+
}
329+
330+
};
331+
//这里是绑定函数的代码;
332+
var handler={
333+
message:"Event handler",
334+
handleClick:function(e){
335+
console.log(this.message);
336+
}
337+
};
338+
var oBtn=document.getElementById("btn");
339+
EventUtil.addHandler(oBtn,"click",handler.handleClick);
340+
341+
</script>
342+
343+
点击后,输出的是undefined;并不是"Event hanler";**原因是没有保存handler.handClick()的运行环境**,this对象最后指的是btn这个ID的按钮;而非hanler; 可以通过代码验证;
344+
345+
var oBtn=document.getElementById("btn");
346+
oBtn.message="这是ID为btn的message属性";
347+
EventUtil.addHandler(oBtn,"click",handler.handleClick);
348+
349+
> 解决办法:包一层函数
350+
351+
var oBtn=document.getElementById("btn");
352+
oBtn.message="这是ID为btn的message属性";
353+
EventUtil.addHandler(oBtn,"click",function(e){
354+
handler.handleClick(e)
355+
});
356+
357+
这个解决方案在 onclick 事件处理程序内使用了一个闭包直接调用 handler.handleClick() 。当然,这是特定于这段代码的解决方案。创建多个闭包可能会令代码变得难于理解和调试。因此,很多JavaScript 库实现了一个可以将函数绑定到指定环境的函数。这个函数一般都叫 bind() 。
358+
359+
function bind(fn,context){
360+
return function(){
361+
return fn.apply(context,arguments);
362+
}
363+
}
364+
//这里是绑定函数的代码;
365+
var handler={
366+
message:"Event handler",
367+
handleClick:function(e){
368+
console.log(this.message+":"+ e.type);
369+
}
370+
};
371+
var oBtn=document.getElementById("btn");
372+
oBtn.message="这是ID为btn的message属性";
373+
EventUtil.addHandler(oBtn,"click",bind(handler.handleClick,handler));
374+
375+
376+
handler.handleClick() 方法和平时一样获得了 event 对象,因为所有的参数都通过被绑定的函数直接传给了它。
377+
378+
ECMAScript 5 为所有函数定义了一个原生的 bind() 方法,进一步简单了操作。换句话说,你不用再自己定义 bind() 函数了,而是可以直接在函数上调用这个方法。
379+
380+
通过输出到控制台查看下;
381+
382+
console.dir(bind);
383+
384+
![](http://i.imgur.com/QtSzMG9.png)
385+
386+
//这里是绑定函数的代码;
387+
var handler={
388+
message:"Event handler",
389+
handleClick:function(e){
390+
console.log(this.message+":"+ e.type);
391+
}
392+
};
393+
var oBtn=document.getElementById("btn");
394+
oBtn.message="这是ID为btn的message属性";
395+
//EventUtil.addHandler(oBtn,"click",bind(handler.handleClick,handler));
396+
EventUtil.addHandler(oBtn,"click",handler.handleClick.bind(handler));//原生的bind方法;
397+
398+
**原生的 bind() 方法与前面介绍的自定义 bind() 方法类似,都是要传入作为 this 值的对象。支持原生 bind() 方法的浏览器有 IE9+、Firefox 4+和 Chrome。**
399+
400+
只要是将某个函数指针以值的形式进行传递,同时该函数必须在特定环境中执行,被绑定函数的效用就突显出来了。它们主要用于**事件处理程序以及 setTimeout() 和 setInterval() **。然而,被绑定函数与普通函数相比有更多的开销,它们需要更多内存,同时也因为多重函数调用稍微慢一点,所以最好只在必要时使用。
401+

test-file.html

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,73 @@
55
<title>Document</title>
66
</head>
77
<body>
8+
<a href="javascript:;" id="btn">00000000000</a>
9+
<script>
10+
//这里是事件工具库;
11+
var EventUtil = {
12+
addHandler: function (element, type, handler) {
13+
if (element.addEventListener) {
14+
element.addEventListener(type, handler, false);
15+
} else if (element.attachEvent) {
16+
element.attachEvent("on" + type, handler);
17+
} else {
18+
element["on" + type] = handler;
19+
}
20+
},
21+
removeHandler: function (element, type, handler) {
22+
if (element.removeEventListener) {
23+
element.removeEventListener(type, handler, false);
24+
} else if (element.detachEvent) {
25+
element.detachEvent("on" + type, handler);
26+
} else {
27+
element["on" + type] = null;
28+
}
29+
},
830

9-
<div id="btn">00000000000</div>
10-
31+
getEvent: function (event) {
32+
return event ? event : window.event;
33+
},
34+
getTarget: function (event) {
35+
return event.target || event.srcElement;
36+
},
37+
preventDefault: function (event) {
38+
if (event.preventDefault) {
39+
event.preventDefault();
40+
} else {
41+
event.returnValue = false;
42+
}
43+
},
44+
stopPropagation: function (event) {
45+
if (event.stopPropagation) {
46+
event.stopPropagation();
47+
} else {
48+
event.cancelBubbles = true;
49+
}
50+
},
51+
getRelatedTarget: function (event) {
52+
if (event.relatedTarger) {
53+
return event.relatedTarget;
54+
} else if (event.toElement) {
55+
return event.toElement;
56+
} else if (event.fromElement) {
57+
return event.fromElement;
58+
} else { return null; }
1159

60+
}
1261

62+
};
1363

14-
<script src="index.js"></script>
15-
<script>
64+
//这里是绑定函数的代码;
1665
var handler={
1766
message:"Event handler",
18-
handleCLick:function(e){
19-
console.log(this.message);
67+
handleClick:function(e){
68+
console.log(this.message+":"+ e.type);
2069
}
2170
};
2271
var oBtn=document.getElementById("btn");
72+
oBtn.message="这是ID为btn的message属性";
73+
// EventUtil.addHandler(oBtn,"click",bind(handler.handleClick,handler));
74+
EventUtil.addHandler(oBtn,"click",handler.handleClick.bind(handler));//原生的bind方法;
2375

2476
</script>
2577
</body>

0 commit comments

Comments
 (0)