第二十二章
JavaScript中的函数非常强大,因为它们是第一类对象。使用闭包和函数环境切换,还可以有很多使用函数的强大方法。可以创建作用域安全的构造函数,确保在缺少new操作符时调用构造函数不会改变错误的环境对象。
- 可以使用惰性载入函数,将任何代码分支推迟到第一次调用函数的时候。
- 函数绑定可以让你创建始终在指定环境中运行的函数,同时函数柯里化可以让你创建已经填了某些参数的函数。
- 将绑定和柯里化组合起来,就能够给你在任意环境中以任意参数执行任意函数的方法。
ECMAScript 5允许通过以下几种方式来创建防篡改对象。
- 不可扩展的对象,不允许给对象添加新的属性或方法。
- 密封的对象,也是不可扩展的对象,不允许删除已有的属性和方法。
冻结的对象,也是密封的对象,不允许重写对象的成员。
JavaScript中可以使用setTimeout()和setInterval()如下创建定时器:定时器代码是放在一个等待区域,直到时间间隔到了之后,此时将代码添加到JavaScript的处理队列中,等待下一次JavaScript进程空闲时被执行。
- 每次一段代码执行结束之后,都会有一小段空闲时间进行其他浏览器处理。
- 这种行为意味着,可以使用定时器将长时间运行的脚本却分为一小块一小块可以在以后运行的代码段。这种做大有助于web应用对用户交互有更积极的响应。
JavaScript中经常以事件的形式应用观察者模式。虽然事件常常和DOM一起使用,但是你也可以通过实现自定义事件在自己的代码中应用。使用自定义事件有助于将不同部分的代码相互之间解耦,让维护更加容易,并减少引入错误的机会。
拖放对于桌面和web应用都是一个非常流行的用户界面范例,它能够让用户非常方便地以一种直观的方式重新排列或者配置东西。在JavaScript中可以使用鼠标事件和一些简单的计算来实现这种功能类型。将拖放行为和自定义事件结合起来可以创建一个可重复使用的框架,它能应用在各种不同的情况下。
以下是拖放的效果图和代码,实测可用:
<!DOCTYPE html>
<html>
<head>
<title>Drag and Drop Example</title>
<script type="text/javascript" src="EventUtil.js"></script>
<script type="text/javascript" src="EventTarget.js"></script>
</head>
<body>
<div id="status"></div>
<div id="myDiv1" class="draggable" style="top:100px;left:0px;background:red;width:100px;height:100px;position:absolute"></div>
<div id="myDiv2" class="draggable" style="background:blue;width:100px;height:100px;position:absolute;top:100px;left:100px"></div>
<script type="text/javascript">
var DragDrop = function(){
var dragdrop = new EventTarget(),
dragging = null,
diffX = 0,
diffY = 0;
function handleEvent(event){
//获取事件和目标
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
//确定事件类型
switch(event.type){
case "mousedown":
if (target.className.indexOf("draggable") > -1){
dragging = target;
diffX = event.clientX - target.offsetLeft;
diffY = event.clientY - target.offsetTop;
dragdrop.fire({type:"dragstart", target: dragging, x: event.clientX, y: event.clientY});
}
break;
case "mousemove":
if (dragging !== null){
//指定位置
dragging.style.left = (event.clientX - diffX) + "px";
dragging.style.top = (event.clientY - diffY) + "px";
//fire custom event
dragdrop.fire({type:"drag", target: dragging, x: event.clientX, y: event.clientY});
}
break;
case "mouseup":
dragdrop.fire({type:"dragend", target: dragging, x: event.clientX, y: event.clientY});
dragging = null;
break;
}
};
//公共接口
dragdrop.enable = function(){
EventUtil.addHandler(document, "mousedown", handleEvent);
EventUtil.addHandler(document, "mousemove", handleEvent);
EventUtil.addHandler(document, "mouseup", handleEvent);
};
dragdrop.disable = function(){
EventUtil.removeHandler(document, "mousedown", handleEvent);
EventUtil.removeHandler(document, "mousemove", handleEvent);
EventUtil.removeHandler(document, "mouseup", handleEvent);
};
return dragdrop;
}();
DragDrop.enable();
DragDrop.addHandler("dragstart", function(event){
var status = document.getElementById("status");
status.innerHTML = "Started dragging " + event.target.id;
});
DragDrop.addHandler("drag", function(event){
var status = document.getElementById("status");
status.innerHTML += "<br>Dragged " + event.target.id + " to (" + event.x + "," + event.y + ")";
});
DragDrop.addHandler("dragend", function(event){
var status = document.getElementById("status");
status.innerHTML += "<br>Dropped " + event.target.id + " at (" + event.x + "," + event.y + ")";
});
</script>
</body>
</html>