比较函数
function compare(value1, value2) {
if (value1 < value2) {
return 1;
} else if (value1 > value2) {
return -1;
} else {
return 0;
}
}
function compare(value1, value2) {
return value2 - value1;
}
function createComparisonFunction(propertyName) {
return function(object1, object2) {
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if(value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
};
}
例如:
var data = [{name:"Zachary", age:28}, {name:"Nicholas", age:29}];
date.sort(createComparisonFunction("name"));
alert(data[0].name);
data.sort(createComparisonFunction("age"));
alert(data[0].name);
函数内部属性
arguments this
例如:
window.color = "red";
var o = {color: "blue"};
function sayColor() {
alert(this.color);
}
sayColor();
o.sayColor = sayColor;
o.sayColor();
函数属性
length prototype caller
说明:caller是一个非标准的属性,一般在函数内部通过arguments.callee.caller使用,推荐用于调试目的。
函数方法
apply() call()
例如:
function sum(num1, num2) {
return num1 + num2;
}
function callSum1(num1, num2) {
return sum.apply(this, arguments);
}
function callSum2(num1, num2) {
return sum.apply(this, [num1, num2]);
}
alert(callSum1(10, 10));
alert(callSum2(10, 10));
window.color = "red";
var o = {color: "blue"};
function sayColor() {
alert(this.color);
}
sayColor();
sayColor.call(this);
sayColor.call(window);
sayColor.call(o);
阶乘函数
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * factorial(num - 1);
}
}
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
例如:
var trueFactorial = factorial;
factorial = function() {
return 0;
};
alert(trueFactorial(5));
alert(factorial(5));
随机数产生函数
值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能的值)
function selectFrom(lowerValue, upperValue) {
var choices = upperValue - lowerValue + 1;
return Math.floor(Math.random() * choices + lowerValue);
}
例如:var num = selectFrom(2, 10);
alert(num);
var colors = ["red", "green", "blue", "yellow", "black", "purple", "brown"];
var color = colors[selectFrom(0, colors.length - 1)];
alert(color);
组合使用构造函数模式和原型模式
例如:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function() {
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 29, "Doctor");
person1.friedds.push("Van");
alert(person1.friends);
alert(person2.friends);
alert(person1.friends === person2.friends);
alert(person1.sayName === person2.sayName);
组合继承
例如:
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
alert(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function() {
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors);
instance1.sayName();
instance1.sayAge();
var instance2 = new SubType("Greg", 27);
alert(instance2.colors);
instance2.sayName();
instance2.sayAge();
模仿块级作用域
例如:
(function() {
var now = new Date();
if(now.getMonth() == 0 && now.getDate() == 1) {
alert("Happy new year!");
}
})();
私有变量
例如:
function MyObject() {
//函数的私有变量
var privateVariable = 10;
function privateFunction() {
return false;
}
//特权方法
this.publicMethod = function() {
privateVariable++;
return privateFunction();
};
}
静态私有变量
(function() {
//私有变量和私有函数
var privateVariable = 10;
function privateFunction() {
return false;
}
//构造函数
MyObject = function() {
};
//公有/特权方法
MyObject.prototype.publicMethod = function() {
privateVariable++;
return privateFunction();
};
})();
(function() {
var name = "";
Person = function(value) {
name = value;
};
Person.prototype.getName = function() {
return name;
};
Person.prototype.setName = function() {
name = value;
};
})();
var person = new Person("Nicholas");
alert(person.getName()); //"Nicholas"
person.setName("Greg");
alert(person.getName()); //"Greg"
var person2 = new Person("Michael");
alert(person1.getName()); //"Michael"
alert(person2.getName()); //"Michael"
模块模式
var singleton = {
name : value,
method : function() {
//这里是方法的代码
}
};
var singleton = function() {
//私有变量和私有函数
var privateVariable = 10;
function privateFunction() {
return false;
}
//特权/公有方法和属性
return {
publicProperty : true,
publicMethod : function() {
privateVariable++;
return privateFunction();
}
};
}();
function BaseComponent() {
}
function OtherComponent() {
}
var application = function() {
//私有变量和函数
var components = new Array();
//初始化
components.push(new BaseComponent());
//公有
return {
getComponentCount : function() {
return components.length;
},
registerComponentCount : function(component) {
if(typeof component == "object") {
components.push(componet);
}
}
};
}();
application.registerComponent(new OtherComponent());
alert(application.getComponentCount());
窗口位置
var leftPos = (typeof window.screenLeft == "number") ?
window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ?
window.screenTop : window.screenY;
window.moveTo(x, y);
window.moveBy(x, y);
窗口大小
var pageWidth = window.innerWidth,
pageHeight = window.innerHeight;
if(typeof pageWidth != "number") {
if(document.compatMode == "CSS1Compat") {
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
window.resizeTo();
window.resizeBy();
检查弹出窗口是否被屏蔽
var blocked = false;
try {
var wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null) {
blocked = true;
} catch (ex) {
blocked = true;
}
if(blocked) {
alert("The popup was blocked!");
}
查询字符串参数
function getQueryStringArgs() {
//取得查询字符串并去掉开头的问号
var qs = (location.search.length > 0 ? location.search.substring(1) : "");
//保存数据的对象
var args = {};
//取得每一项
var items = qs.split("&");
var item = null,
name = null,
value = null;
//逐个将每一项添加到args对象中
for (var i=0; i<items.length; i++) {
item = items[i].split("=");
name = decodeURIComponent(item[0]);
value = decodeURIComponent(item[1]);
args[name] = value;
}
return args;
}
例如:
假设查询字符串是?q=javascript&num=10
var args = getQueryStringArgs();
alert(args["q"]);
alert(args["num"]);
遍历元素的特性
function outputAttributes(element) {
var pairs = new Array();
for(var i=0, len=element.attributes.length; i<len; i++) {
var attrName = element.attributes[i].nodeName;
var attrValue = element.attributes[i].nodeValue;
if(element.attributes[i].specified) {
pairs.push(attrName + "=\"" + attrValue + "\"");
}
}
return pairs.join(" ");
}
ie bug
if(client.browser.ie && client.browser.ie<=7) {
var iframe = document.createElement("<iframe name=\"myframe\"></iframe>");
var input = document.createElement("<input name=\"checkbox\">");
var button = document.createElement("<button name=\"reset\"></button>");
var radio1 = document.createElement("<input type=\"radio\" name=\"choice\" value=\"1\">");
var radio2 = document.createElement("<input type=\"radio\" name=\"choice\" value=\"2\">");
}
通用的contains()函数
function contains(refNode, otherNode) {
if (typeof refNode.contains == "funciton" && (!client.engine.webkit || client.engine.webkit >= 522)) {
return refNode.contains(otherNode);
} else if (typeof refNode.compareDocumentPosition == "function") {
return !!(refNode.compareDocumentPosition(otherNode) & 16);
} else {
var node = otherNode.parentNode;
do {
if (node === refNode) {
return true;
} else {
node = node.parentNode;
}
} while (node !==null);
return false;
}
}
通用innerText
function getInnerText(element) {
return (typeof element.textContent == "string") ? element.textContent : element.innerText;
}
function setInnerText(element, text) {
if (typeof element.textContent == "string") {
element.textContent = text;
} else {
element.innerText = text;
}
}
动态脚本
function loadScript(url) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
document.body.appendChild(script);
}
loadScript("client.js");
function loadScriptString(code) [
var script = document.createElement("script");
script.type = "text/javascript";
try {
script.appendChild(document.createTextNode(code));
} catch (ex) {
script.text = code;
}
document.body.appendChild(script);
}
loadScriptString("function sayHi(){alert('hi');}");
动态样式
function loadStyles(url) {
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css";
link.href = url;
var head = document.getElementByTagName("head")[0];
head.appendChild(link);
}
loadStyles("styles.css");
function loadStyleString(css) {
var style = document.createElement("style");
style.type = "text/css";
try {
style.appendChild(document.createTextNode(css));
} catch (ex) {
style.styleSheet.cssText = css;
}
var head = document.getElementByTagName("head")[0];
head.appendChild(style);
}
loadStyleString("body{background-color:red}");
访问框架或内嵌框架的文档对象
var iframe = document.getElementById("myIframe");
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
偏移量
function getElementLeft(element) {
var actualLeft = element.offsetLeft;
var current = element.offsetParent;
while (current !== null) {
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
return actualLeft;
}
function getElementTop(element) {
var actualTop = element.offsetTop;
var current = element.offsetParent;
while (current !== null) {
actualTop += current.offsetTop;
current = current.offsetParent;
}
return actualTop;
}
客户区大小
浏览器视口大小
function getViewport() {
if (document.compatMode == "BackCompat") {
return {
width : document.body.clientWidth,
height : document.body.clientHeight
};
} else {
return {
width : document.documentElement.clientWidth,
height : document.documentElement.clientHeight
};
}
}
文档的总高度
var docHeight = Math.max(document.documentElement.scrollHeight,
document.documentElement.clientHeight);
var docWidth = Math.max(document.documentElement.scrollWidth,
document.documentElement.clientWidth);
控制滚动条
function scrollToTop(element) {
if (element.scrollTop != 0) {
element.scrollTop = 0;
}
}
function getBoundingClientRect(element) {
var scrollTop = document.documentElement.scrollTop;
var scrollLeft = document.documentElement.scrollLeft;
if (element.getBoundingClientRect) {
if (typeof arguments.callee.offset != "number") {
var temp = document.createElement("div");
temp.style.cssText = "position:absolute; left:0; top:0;";
document.body.appendChild(temp);
arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop;
document.body.removeChild(temp);
temp = null;
}
var rect = element.getBoundingClientRect();
var offset = arguments.callee.offset;
return {
left : rect.left + offset,
right : rect.right + offset,
top : rect.top + offset,
bottom : rect.bottom + offset
};
} else {
var actualLeft = getElementLeft(element);
var actualTop = getElementTop(element);
return {
left : actualLeft - scrollLeft,
right : actualLeft + element.offsetWidth - scrollLeft,
top : actualTop - scrollTop,
bottom : actualTop + element.offsetHeight - scrollTop
};
}
}
DOM0级事件处理程序
var btn = document.getElementById("myBtn");
btn.onclick = function() {
alert("Clicked");
}
DOM2级事件处理程序
firefox事件处理程序
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function() {
alert(this.id);
}, false);
btn.addEventListener("click", function() {
alert("Hello world!");
}, false);
这里为按钮添加了两个事件处理程序,这两个事件处理程序会按照添加它们的顺序触发,因此首先会显示元素Id,其次会显示"Hello world!"消息。
var btn = document.getElementById("myBtn");
var handler = function() {
alert(this.id);
};
btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false);
IE事件处理程序
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
alert(this === window); //true
});
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function() {
alert("Clicked");
});
btn.attachEvent("onclick", function() {
alert("Hello world!");
});
这里调用了两次attachEvent(),为同一个按钮添加了两个不同的事件处理程序,这些事件处理程序不是以添加它们的顺序执行,而是以相反的顺序执行。
var btn = document.getElementById("myBtn");
var handler = function() {
alert("Clicked");
};
btn.attachEvent("onclick", handler);
btn.detachEvent("onclick", handler);
跨浏览器的事件处理程序
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on", + type, handler);
} else {
element["on" + type] = handler;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on", + type, handler);
} else {
element["on" + type] = null;
}
},
};
例如:
var btn = document.getElementById("myBtn");
var handler = function() {
alert("Clicked");
};
EventUtil.addHandler(btn, "click", handler);
EventUtil.removeHandler(btn, "click", handler);
DOM中的事件对象
var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
alert(event.type); //"click"
};
btn.addEventListener("click", function(event) {
alert(event.type); //"click"
}, false);
在事件处理程序内部,对象this始终等于currentTarget的值,而target则只包含事件的实际目标。如果直接将事件处理程序指定给了目标元素,则this、currentTarget和target包含相同的值。
var btn = document.getElementById("myBtn");
btn.onclick = function(event) {
alert(event.currentTarget === this); //true
alert(event.target === this); //true
};
document.body.onclick = function(event) {
alert(event.currentTarget === document.body); //true
alert(this === document.body); //true
alert(event.target === document.getElementById("myBtn")); //true
};
通过一个函数处理多个事件
var btn = document.getElementById("myBtn");
var handler = function(event) {
switch(event.type) {
case "click":
alert("Click");
break;
case "mouseover":
event.target.style.backgroundColor = "red";
break;
case "mouseout":
event.target.style.backgroundColor = "";
break;
}
};
btn.onclick = handler;
btn.onmouseover = handler;
btn.onmouseout = handler;
跨浏览器的事件对象
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on", + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function(event) {
return event ? window.event;
},
getTarget: function(event) {
return event.target || event.srcElement;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on", + type, handler);
} else {
element["on" + type] = null;
}
},
stopPropagation: function(event) {
if (event.stopPropatation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
getRelatedTarget: function(event) {
if (event.relatedTarget) {
return event.relatedTarget;
} else if (event.toElement) {
return event.toElement;
} else if (event.fromElement) {
return event.fromElement;
} else {
return null;
}
},
getButton: function(event) {
if (document.implementation.hasFeature("MouseEvents", "2.0")) {
return event.button;
} else {
switch(event.button) {
case 0:
case 1:
case 3:
case 5:
case 7:
return 0;
case 2:
case 6:
return 2;
case 4:
return 1;
}
}
}
};
事件委托
<ul id="muLinks">
<li id="goSomeshere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
switch(target.id){
case "doSomething":
document.title = "I changed the document's title";
break;
case "goSomewhere":
location.href = "http"//www.wrox.com";
break;
case "sayHi":
alert("hi");
break;
}
});
最适合采用事件委托技术的事件包括click、mousedown、mouseup、keydown、keyup和keypress
//避免多次提交表单
EventUtil.addHandler(form, "submit", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
//取得提交按钮
var btn = target.elements["submit-btn"];
//禁用它
btn.disabled = true;
});
focus和blur事件以某种方式改变用户界面
var textbox = document.forms[0].element[0];
EventUtil.addHandler(textbox, "focus", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if(target.style.backgroundColor != "red"){
target.style.backgroundColor = "yellow";
}
});
EventUtil.addHandler(textbox, "blur", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if(/[^\d]/.test(target.value)){
target.style.backgroundColor = "red";
} else {
target.style.backgroundColor = " ";
}
});
EventUti.addHandler(textbox, "change", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
if(/[^\d]/.test(target.value)){
target.style.backgroundColor = "red";
} else {
target.style.backgroundColor = " ";
}
});
文本框获得焦点
EventUtil.addHandler(textbox, "focus", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
target.select();
});
取得选择的文本
functin getSelectedText(textbox){
if(document.selection){
return document.selection.createRange().text;
} else {
return textbox.value.substring(textbox.selectionStart, textbox.selectionEnd);
}
}
选择部分文本
function selectText(textbox, startIndex, stopIndex){
if(textbox.setSelectionRange){
textbox.setSelectionRange(startIndex, stopIndex);
} else if(textbox.createTextRange){
var range = textbox.createTextRange();
range.collapse(true);
range.moveStart("character", startIndex);
range.moveEnd("character", stopIndex - startIndex);
range.select();
}
textbox.focus();
}
例如:
textbox.value = "Hello world";
//选择所有文本
selectText(textbox, 0, textbox.value.length); //"Hello world!"
//选择前3个字符
selectText(teextbox, 0, 3); //"Hel"
//选择第4到第6个字符
selectText(textbox, 4, 7); //"o w"
过滤输入
EventUtil.addHandler(textbox, "keypress", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
var charCode = EventUtil.getCharCode(event);
if(!/\d/.test(String.fromCharCode(charCode)) && charCode > 9 && !event.ctrlKey){
EventUtil.preventDefault(event);
}
});
自动切换焦点
<input type="text" name="tel1" id="txtTel1" maxlength="3">
<input type="text" name="tel2" id="txtTel2" maxlength="3">
<input type="text" name="tel3" id="txtTel3" maxlength="3">
(function(){
function tabForward(event);
var target = EventUtil.getTarget(evet);
if(target.value.length == target.maxLength){
var form = target.form;
for(var i=0, len = form.elements.length; i<len; i++){
if (form.elements[i] == target) {
form.elements[i+1].focus();
return;
}
}
}
var textbox1 = docuemnt.getElementById("txtTel1");
var textbox2 = docuemnt.getElementById("txtTel2");
var textbox3 = docuemnt.getElementById("txtTel3");
EventUtil.addHandler(textbox1, "keyup", tabForward);
EventUtil.addHandler(textbox2, "keyup", tabForward);
EventUtil.addHandler(textbox3, "keyup", tabForward);
})();
添加选项
var newOption = document.createElement("option");
newOption.appendChild(document.createTextNode("Option text"));
newOption.setAttribute("value", "Option value");
selectbox.appendChild(newOption);
var newOption = new Option("Option text", "Option value");
selectbox.add(newOption, undefined);
移除选项
selectbox.removeChild(selectbox.option[0]); //移除第一个选项
selectbox.remove(0);
selectbox.option[0] = null;
function clearSelectbox(selectbox) {
for(var i=0, len=selectbox.options.length; i<len; i++) {
selectbox.remove(0);
}
}
移动和重排选项
var selectbox1 = document.getElementById("selLocation1");
var selectbox2 = document.getElementById("selLocation2");
selectbox2.appendChild(selectbox1.option[0]);
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index-1]);
var optionToMove = selectbox.options[1];
selectbox.insertBefore(optionToMove, selectbox.options[optionToMove.index+2]);
表单序列化
function serialize(form) {
var parts = new Array();
var field = null;
for (var i=0, len=form.elements.length; i<len; i++) {
field = form.elements[i];
switch(field.type) {
case "select-one":
case "select-multiple":
for (var j=0, optLen=field.options.length; i<optLen; j++) {
var option = field.options[j];
if (option.selected) {
var optValue = "";
if (option.hasAttribute) {
optValue = (option.hasAttribute("value") ?
option.value : option.text);
} else {
optValue = (option.attributes["value"].specified ?
option.value : option.text);
}
parts.push(encodeURIComponent(field.name) + "=" +
encodeURIComponent(optValue));
}
}
break;
case undefined: //字段集
case "file": //文件输入
case "submit": //提交按钮
case "reset": //重置按钮
case "button": //自定义按钮
break;
case "radio": //单选按钮
case "checkbox": //复选框
if (!field.checked) {
break;
}
/* 执行默认操作 */
default:
parts.push(encodeURIComponent(field.name) + "=" +
encodeURIComponent(field.value));
}
}
return parts.join("&");
}
try-catch语句
try{
// 可能会导致错误的代码
} catch(error) {
// 在错误发生时怎么处理
}
例如:
try {
window.someNonexistentFunction(); //调用不存在的函数
} catch (error) {
alert(error.message);
}
finally子句
例如:
function testFinally() {
try {
return 2;
} catch (error) {
return 1;
} finally {
return 0;
}
} // 返回0
抛出错误
function process(values) {
if (!(values instanceof Array)) {
throw new Error("process() : Argument must be an array.");
}
values.sort();
for (var i=0, len=values.length; i<len; i++) {
if (values[i]>100) {
return values[i];
}
}
return -1;
}
捕获错误的目的在于避免浏览器以默认的方式处理它们;而抛出错误的目的在于提供错误发生具体原因的消息。
错误事件
window.onerror = function(message, url, line) {
alert(message);
}
window.onerror = function(message, url, line) {
return false;
}
只要能够适当的使用try-catch语句,就不会有错误交给浏览器,也就不会触发error事件。
图像也支持error事件
var image = new Image();
EventUtil.addHandler(image, "load", function(event) {
alert("Image loaded!");
});
EventUtil.addHandler(image, "error", function(event) {
alert("Image not loaded!");
});
image.src = "smilex.gif"; // 指定不存在的文件
大体上来说,基本类型的值应该使用typeof来检测,而对象的值应该使用instanceof来检测
function getQueryString(url) {
if (typeof url == "string") {
var pos = url.indexOf("?");
if (pos>-1) {
return url.substring(pos + 1);
}
}
return "";
}
function reverseSort(values) {
if (values instanceof Array) {
values.sort();
values.reverse();
}
}
通信错误
function addQueryStringArg(url, name, value) {
if (url.indexOf("?") == -1) {
url += "?";
} else {
url += "&";
}
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
例如:
var url = "http://www.somedomain.com";
var newUrl = addQueryStringArg(url, "redir",
"http://www.someotherdomain.com?a=b & c=d");
alert(newUrl);
区分致命错误和非致命错误
for (var i=0, len=mods.length; i<len; i++) {
try {
mods[i].init();
} catch (ex) {
// 在这里处理错误
}
}
把错误记录到服务器
function logError(sev, msg) {
var img = new Image();
img.src = "log.php?nev=" + endoceURIComponent(sev) + "&msg=" +
encodeURIComponent(msg);
}
例如:
for (var i=0, len=mods.length; i < len; i++) {
try {
mods[i].init();
} catch (ex) {
logError("nonfatal", Module init failed: " + ex.message);
}
}
调试技术
将消息记录到控制台
function sum(num1, num2) {
console.log("Entering sum(), arguments are " + num + "," + num2);
console.log("Before calculation");
var result = num1 + num2;
console.log("After calculation");
console.log("Exiting sum()");
return result;
}
function sum(num1, num2) {
java.lang.System.out.println("Entering sum(), arguments are " + num1 + "," + num2);
java.lang.System.out.println("Before calculation");
var result = num1 + num2;
java.lang.System.out.println("After calculation");
java.lang.System.out.println("Exiting sum()");
return result;
}
function log(message) {
if (typeof console == "object") {
console.log(message);
} else if (typeof opera == "object") {
opera.postError(message);
} else if (typeof java == "object" && typeof java.lang == "object") {
java.lang.System.out.println(message);
}
}
将消息记录到当前页面
function log(message) {
var console = document.getElementById("debuginfo");
if (console === null) {
console = document.createElement("div");
console.id = "debuginfo";
console.style.background = "#dedede";
console.style.border = "1px solid silver";
console.style.padding = "5px";
console.style.width = "400px";
console.style.position = "absolute";
console.style.right = "0px";
console.style.top = "0px";
document.body.appendChild(console);
}
console.innerHTML += " <p> " + message + " </p> ";
}
抛出错误
function divide(num1, num2) {
if (typeof num1 != "number" || typeof num2 != "number") {
throw new Error("divide(): Both arguments must be numbers.");
}
return num1 / num2;
}
function assert(condition, message) { //condition是求值结果应该为true的条件,message是条件为false时要抛出的错误
if (!condition) {
throw new Error(message);
}
}
例如:
function divide(num1, num2) {
assert(typeof num1 == "number" && typeof num2 == "number",
"divide(): Both arguments must be numbers.");
return num1 / num2;
}
xml
将xml解析为DOM文档
DOMParser类型
var parser = new DOMParser();
var xmldom = parser.parseIromString("<root><child/></root>", "text/xml");
alert(xmldom.documentElement.tagName); //"root"
alert(xmldom.documentElement.firstChild.tagName); //"child"
var anotherChild = xmldom.createElement("child");
xmldom.documentElement.appendChild(anotherChild);
var children = xmldom.getElementsByTagName("child");
alert(children.length); //2
var parser = new DOMParser();
var xmldom = parser.parseFromString("<root>", "text/xml");
var errors = xmldom.getElementsByTagName("parsererror");
if (errors.length > 0) {
alert("Parsing error!");
}
将DOM文档序列化为xml字符串
XMLSerializer类型
var serializer = new XMLSerializer();
var xml = serializer.serializeToString(xmldom);
alert(xml);
IE加载XML文件
var xmldom = createDocument();
xmldom.async = false;
xmldom.load("example.xml");
if (xmldom.parseError != 0) {
alert("An error occurred:\nError Code: "
+ xmldom.parseError.errorCode + "\n"
+ "Line: " + xmlcom.parseError.line + "\n"
+ "Line Pos: " + xmldom.parseError.linepos + "\n"
+ "Reason: " + xmldom.parseError.reason);
} else {
alert(xmldom.documentElement.tagName); //"root"
alert(xmldom.documentElement.firstChild.tagName); //"child"
var anotherChild = xmldom.createElement("child");
xmldom.documentElement.appendChild(antherChild);
var children = xmldom.getElementsByTagName("child");
alert(chilren.length); //2
alert(xmldom.xml);
}
var xmldom = createDocument();
xmldom.async = true;
xmldom.onreadystatechange = function() {
if (xmldom.readyState == 4) {
if (xmldom.parseError != 0) {
alert("An error occurred:\nError Code: "
+ xmldom.parseError.errorCode + "\n"
+ "Line: " + xmlcom.parseError.line + "\n"
+ "Line Pos: " + xmldom.parseError.linepos + "\n"
+ "Reason: " + xmldom.parseError.reason);
} else {
alert(xmldom.documentElement.tagName); //"root"
alert(xmldom.documentElement.firstChild.tagName); //"child"
var anotherChild = xmldom.createElement("child");
xmldom.documentElement.appendChild(antherChild);
var children = xmldom.getElementsByTagName("child");
alert(chilren.length); //2
alert(xmldom.xml);
}
}
};
xmldom.load("example.xml");
跨浏览器处理XML
function parseXml(xml) {
var xmldom = null;
if (typeof DOMParser != "undefined") {
xmldom = (new DOMParser()).parseFromString(xml, "text/xml");
var errors = xmldom.getElementsByTagName("parsererror");
if (errors.length) {
throw new Error("XML parsing error:" + errors[0].textContent);
}
} else if (document.implementation.hasFeature("Ls", "3.0)) {
var implementation = document.implementation;
var parser = implementation.createLSParser(implementation.MODE_SYNCHRONUS, null);
var input = implementation.createLSInput();
input.stringData = xml;
xmldom = parser.parse(input);
} else if (typeof ActiveXobject != "undefined") {
xmldom = createDocument();
xmldom.loadXML(xml);
if (xmldom.parseError != 0) {
throw new Error("XML parsing error: " + xmldom.parseError.reason);
}
} else {
throw new Error("No XML parser available.");
}
return xmldom;
}
例如:
var xmldom = null;
try {
xmldom = parseXml("<root><child/></root>");
} catch (ex) {
alert(ex.message);
}
跨浏览器序列化XML
function serializeXml(xmldom) {
if (typeof XMLSerializer != "undefined") {
return (new XMLSerializer()).serizlizeToString(xmldom);
} else if (document.implementation.hasFeature("LS", "3.0")) {
var implementation = document.implementation;\
var serializer = implementation.createLSSerializer();
return serializer.writeToString(xmldom);
} else if (typeof xmldom.xml != "undefined") {
return xmldom.xml;
} else {
throw new Error("Could not serialize XML DOM.");
}
}
例如:
var xml = serializeXml(xmldom);
DOM3级XPath
var supportsXPath = document.implementation.hasFeature("XPath", "3.0");
Ajax
XMLHttpRequest对象(简称XHR)
创建XHR对象
//适用于IE7之前的版本
function createXHR() {
if (typeof arguments.callee.activeXString != "string") {
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"];
for (var i=0, len=versions.length; i < len; i++) {
try {
var xhr = new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
return xhr;
} catch (ex) {
//跳过
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
}
IE7、Firefox、Opera、Chrome和Safari都支持原生的XHR对象
var xhr = new XMLHttpRequest();
跨浏览器创建XHR对象
function createXHR() {
if (typeof XMLHttpRequest != "undefined") {
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined") {
if (typeof arguments.callee.activeXString != "string") {
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"];
for (var i=0, len=versions.length; i < len; i++) {
try {
var xhr = new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
return xhr;
} catch (ex) {
//跳过
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error("No XHR objectt available.");
}
}
XHR的用法
要调用的第一个方法open()
xhr.open("get", "example.php", false); //启动一个针对example.php的请求
发送同步请求
xhr.open("get", "example.txt", false);
xhr.send(null);
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.statusText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
readyState属性
0:未初始化。尚未调用open()方法。
1:启动。已经调用open()方法。
2:发送。已经调用send()方法,但尚未接收到响应。
3:接收。已经接收到部分响应数据。
4:完成。已经接收到全部响应数据,而且已经可以在客户端使用了。
var xhr = createXHR();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "example.txt", true);
xhr.send(null);
HTTP头部信息
setRequestHeader()方法可以设置自定义的请求头部信息
var xhr = createXHR();
xhr.onreadystatechange = function(event) {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "example.txt", true);
xhr.setRequestHeader("MyHeader", "MyValue");
xhr.send(null);
调用XHR对象的getResponseHeader()方法并传入头部字段名称,可以取得相应的响应头部信息
而调用getAllResponseHeaders()方法可以取得一个包含所有头部信息的长字符串
var myHeader = xhr.getResponseHeader("MyHeader");
var allHeaders = xhr.getAllResponseHeaders();
GET请求
对于XHR而言,位于传入open()方法的URL末尾的查询字符串必须经过正确的编码才行
查询字符串中每个参数的名称和值都必须使用endoceURIComponent()进行编码,然后才能放到URL的末尾;而且所有名-值对都必须由和好(&)分隔
例如:
xhr.open("get", "example.php?namel=value& name2=value2", true);
辅助向现有URL的末尾添加查询字符串参数
function addURLParam(url, name, value) {
url += (ul.indeOf("?") == -1 ? "?" : "&");
url += endodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
例如:
var url = "example.php";
//添加参数
url = addURLParam(url, "name", "Nicholas");
url = addURLParam(url, "book", "Professional JavaScript");
//初始化请求
xhr.open("get", url, false);
POST请求
通常用于向服务器发送应该被保存的数据
POST请求应该把数据作为请求的主体提交,而GET请求传统上不是这样
xhr.open("post", "example.php", true);
使用XHR模仿表单提交:首先将Content-Type头部信息设置为appliaction/x-www-form-urlencoded,也就是表单提交时的内容类型,其次是以适当格式创建一个字符串
function submitData() {
var xhr = createXHR();
xhr.onreadystatechange = function(event) {
if (xhr.readyState == 4) {
if ((xhr.status >=200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("pose", "postexample.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var form = document.getElementById("user-info");
xhr.send(serialize(form));
}
<?php
header("Content-Type: text/plain");
echo <<<EOF
Name: {$_POST['user-name']}
Email: {$_POST['user-email']}
EOF;
?>
浏览器差异
IE8为XHR对象添加了一个timeout属性,表示请求在等待响应多少毫秒之后就终止
var xhr = createXHR();
xhr.onreadystatechange = function(event) {
try {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
} catch (ex) {
//假设由ontimeout事件处理程序处理
}
};
xhr.open("get", "timeout.php", true);
xhr.timeout = 1000;
xhr.ontimeout = function() {
alert("Request did not return in a second.");
};
xhr.send(null);
Firefox、Opera、Chrome和Safari都实现了load事件替代readystatechange事件
var xhr = createXHR();
xhr.onload = funciton(event) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert(Request was unsuccessful: " + xhr.status);
}
};
xhr.open("get", "altevents.php", true);
xhr.send(null);
为用户创建进度指示器
var xhr = createXHR();
xhr.onload = function(event) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
};
xhr.onprogress = function(event) {
var divStatus = document.getElementById("status");
divStatus.innerHTML = "Received " + event.position + " of " + event.totalSize + " bytes";
};
xhr.open("get", "altevents.php", true);
xhr.send(null);
跨域请求
XDomainRequest对象
var xdr = new XDomainRequest();
xdr.onload = function() {
alert(xdr.responseText);
};
xdr.open("get", "http://www.somewhere-else.com/page/");
xdr.send(null);
要检测错误,可以像下面这样指定一个onerror事件处理程序
var xdr = new XDdmainRequest();
xdr.onload = funciton() {
alert(xdr.responseText);
};
xdr.onerror = function() {
alert("An error occurred.");
};
xdr.open("get", "http://www.somewhere-else.com/page/");
xdr.send(null);
与XHR一样,XDR对象也支持timeout属性以及ontimeout事件处理程序
var xdr = new XDomainRequest();
xdr.onload = function() {
alert(xdr.responseText);
};
xdr.onerror = function() {
alert("An error occurred.");
};
xdr.timeout = 1000;
xdr.ontimeout = function() {
alert("Request took too long.");
};
xdr.open("get", "http://www.somewhere-else.com/page/");
xdr.send(null);
为支持POST请求,XDR对象提供了contentType属性,用来表示发送数据的格式
var xdr = new XDomainRequest();
xdr.onload = function() {
alert(xdr.responseText);
};
xdr.onerror = function() {
alert("An error occurred.");
};
xdr.open("post", "http://www.somewhere-else.com/page/");
xdr.contentType = "application/x-www-form-urlencoded";
xdr.send("namel=value1 & name2=value2");
跨域XHR
var xhr = createXHR();
xhr.onreadystatechange = funciton() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
} else {
alert("Request was unsuccessful: " + xhr.status);
}
}
};
xhr.open("get", "http://www.somewhere-else.com/page/", true);
xhr.send(null);
在Ajax中使用JSON
var jsonText = "{\"name\":\"Nicholas C. Zakas\", \"age\":29, \"author\":true}";
var object = JSON.parse(jsonText, function(key, value) {
switch(key) {
case "age": return value + 1;
case "author": return undefined;
default: return value;
}
});
alert(object.age); //30;
alert(object.author); //undefined
假设addressbook.php会以下面的格式返回JSON数据
[
{
"name": "Nicholas C. Zakas",
"email": "nicholas@some-domain-name.com"
},
{
"name": "Jim Smith",
"email": "Jimsmith@some-domain-name.com"
},
{
"name": "Michael Jones"<
"email": "mj@some-domain-name.com"
}
]
可以发送一个Ajax请求取得以上数据,然后在客户端使用下列代码生成相应的<ul/>元素
var xhr = createXHR();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
var contacts = JSON.parse(xhr.responseText);
var list = document.getElementById("contacts");
for (var i=0, len=contacts.length; i < len; i++) {
var li = document.createElement("li");
li.innerHTML = "<a href=\"mailto:" + contacts[i].email + "\">" +
contacts[i].name + "<\a>";
list.appendChild(li);
}
}
}
};
xhr.open("get", "addressbook.php", true);
xhr.send(null);
JSON对象的stringify()方法
var contact = {
name: "Nicholas C.Zakas",
email: "nicholas@some-domain-name.com"
};
var jsonText = JSON.stringify(contact);
alert(jsonText); //{\"name\":\Nicholas C. Zakas\",\:email\":\"nicholas@some-domain-name.com \"}
var jsonText = JSON.stringify([new Function()], function(key, value) {
if (value instanceof Function) {
return "(function)";
} else {
return value;
}
});
alert(jsonText); //"[(function)]"
使用POST请求并将JSON文本传给send()方法,可以将JSON数据发送给服务器
var xhr = createXHR();
var contact = {
name: "Ted Jones",
email: "tedjones@some-other-domain.com"
};
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
alert(xhr.responseText);
}
}
};
xhr.open("post", "addcontact.php", true);
xhr.send(JSON.stringify(contact));
作用域安全的构造函数
function Person(name, age, job) {
if (this instanceof Person) {
this.name = name;
this.age = age;
this.job = job;
} else {
return new Person(name, age, job);
}
}
var person1 = Person("Nicholas", 29, "Sofeware Engineer");
alert(window.name); //" "
alert(person1.name); //"Nicholas"
var person2 = new Person("Shelby", 34, "Ergonomist");
alert(person2.name); //"Shelby"
构造函数窃取结合使用原型链或者寄生组合
function Polygon(sides) {
if (this instanceof Polygon) {
this.sides = sides;
this.getArea = function() {
return 0;
};
} else {
return new Polygon(sides);
}
}
function Rectangle(width, height) {
Polygon.call(this, 2);
this.width = width;
this.height = height;
this.getArea = function() {
return this.width * this.height;
};
}
Rectangle.prototype = new Polygon();
var rect = new Rectangle(5, 10);
alert(rect.sides); //2
惰性载入函数
function createXHR() {
if (typeof XMLHttpRequest != "undefined") {
createXHR = function() {
return new XMLHttpRequest();
};
} else if (typeof ActiveXObject != "undefined") {
createXHR = function() {
if (typeof arguments.callee.activeXString != "string") {
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"];
for (var i=0, len=versions.length; i < len; i++) {
try {
var xhr = new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
return xhr;
} catch (ex) {
//skip
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
};
} else {
createXHR = function() {
throw new Error("No XHR object available.");
};
}
return createXHR();
}
函数绑定
var handler = {
message: "Event handled",
handleClick: function(event) {
alert(this.message);
}
};
var btn = document.getElementById("my-btn");
EventUtil.addHandler(btn, "click", handler.handleClick);
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);
});
function bind(fn, context) {
return function() {
return fn.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.handleClick, handler));
例如:
var handler = {
message: "Event handled",
handleClick: function(event) {
alert(this.message + ":" + event.type);
}
};
var btn = document.getElementById("my-btn");
EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler));
函数柯里化
function add(num1, num2) {
return num1 + num2;
}
function curriedAdd(num2) {
return add(5, num2);
}
alert(add(2, 3)); //5
alert(curriedAdd(3)); //8
柯里化函数的通用方式
function curry(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(null, finalArgs);
};
}
例如:
function add(num1, num2) {
return num1 + num2;
}
var curriedAdd = curry(add, 5);
alert(curriedAdd(3)); //8
给出所有的函数参数
function add(num1, num2) {
return num1 + num2;
}
var curriedAdd = curry(add, 5, 12);
alert(curriedAdd()); //17
函数柯里化还常常作为函数绑定的一部分包含在其中,构造出更为复杂的bind()函数
function bind(fn, context) {
var args = Array.prototype.slice.call(arguments, 2);
return function() {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(context, finalArgs);
};
}
var handler = {
message: "Event handled",
handleClick: function(name, event) [
alert(this.message + ":" + event.type);
}
};
var btn = document.getElementById("my-btn");
EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler, "my-btn"));
javascript精粹
最新推荐文章于 2022-12-11 22:50:32 发布