阅读了<编写高质量代码: 改善js程序的188个建议>后, 摘录了一些好的例子,记录之….
惰性载入函数
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" + type, handle);
};
// 由于前面修改了addEvent的函数, 所以必须重新执行一次
// 在函数内部改变自身的方式
addEvent(el, type, handle);
}
函数绑定
function bind(fn, context) {
return fn.apply(context, arguments);
}
高阶函数
function map(array, fn) {
var res = [];
for(var i = 0, len = array.length; i < len; i++) {
res.push(fn(array[i]);
}
}
var mapped =map([1, 3, 5, 7], function(n) {
return n = n + 1;
}); // [2, 4, 6, 8]
函数节流
- 应用环境 规定一个事件在指定的时间只能被调用一次
例如监听窗口resize的事件 会直到用户停止拖动才会响应事件
var processor = { // 在规定间隔内只能执行一次 timeoutId : 0, // 实际进行处理的方法 performProcessing: function() { // 实际执行的方法 }, process: function() { clearTimeout(timeoutId); var that = this; this.timeoutId = setTimeout(function() { that.performProcessing(); }, 100); } } // 尝试开始执行 processor.process();
简化模式
function throttle(method, context) { clearTimeout(method.tId); method.tId = setTimeout(function() { method.call(context); }, 100); }
作用域安全的构造函数
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);
rect.getArea(); // -> 50
rect.sides; // -> 2
使用原型来实现数据备份
原理是利用原型对象来储存实例对象的所有可枚举的属性
P.prototype[i] = this[i];
function P(x) {
this.x = x;
}
P.prototype.backUp = function() {
for (var i in this) {
P.prototype[i] = this[i];
}
};
var p1 = new P(1);
p1.backUp();
p1.x; // -> 1
p1.x = 10;
p1.x; // -> 10
p1 = P.prototype;
p1.x; // -> 1
批量修改原型对象
这样如果想要修改所有复制到实例的x值 只需要修改原型对象中的值 就可以了
function F(x) {
this.x = x;
}
var a = [];
function Temp() {}
Temp.prototype = new F(10);
for (var i = 0; i < 10; i++) {
a[i] = new Temp();
}
函数的引用和调用
函数的调用能够改变函数的执行作用域
var o = {
name: "object o",
f: function() {
return this;
}
};
o.o1 = {
name: "object o1",
me: o.f // 引用了o.f的方法
}
var who = o.o1.me();
who.name; // -> "object o1"
o.o2 = {
name: "object o2",
// 改变了当前的执行作用域
me: o.f() // 调用了o.f的方法
}
var who = o.o2.me;
who.name; // -> "object o"
快速打印一个五分制的评分情况
function getRating(rating) {
if(rating > 5 || rating < 0) {
throw new Error('数字不在范围内");
} else {
return "★★★★★☆☆☆☆☆".slice(5 - rating, 10 - rating);
}
}
getRating(3); // -> '★★★☆☆'
输出n个”abc”拼接成的字符串
var str = new Array(n + 1).join("abc");
jQuery 处理文档加载
jQuery.ready.promise = function(obj) {
if (!readyList) {
readyList = jQuery.Deferred();
if (document.radyState === "complete") {
setTimeout(jQuery.ready);
} else {
document.addEventListener("DOMContentLoaded", completed, false);
window.addEventListener("load", completed, false);
}
}
return readyList.promise(obj);
};
jQuery中执行noConflict函数的理解
1. 首先在<head></head>中可以插入脚本,比如是prototype.js和jQuery.js库
2. 在导入jQuery.js的时候,将prototype.js中的$进行保存, var _$ = window.$;
3. jQuery.js完全导入后,此时的window.$已经被替换成了jQuery中$
4. 当执行noConflict函数, 此时的window.$ === jQuery 成立,系统会将window.$ 替换成之前保存_$, 即prototype中的$
5. 此时即完成了jQuery让出$控制权的功能
6. 应该注意在加载jQuery之前已经存在一个$命名空间的的库,否则 var _$ = window.$就没有意义了
使用Cookie存储长信息
- 读取所用cookie信息,包括子cookie信息
- 返回: 对象 存储cookie值
bug: 测试数据无法中的过期时间无法加入到o对象中去
function getSubCookie() { var a = document.cookie.split(";"); console.log(a.length); var o = {}; for (var i = 0; i < a.length; i++) { // 消除a[i]字符串中的头部尾部字符串 类似于trim()函数 a[i] && (a[i] = a[i].replace(/^\s+|\s+$/, "")); var b = a[i].split("="); var c = b[1]; c && (c = c.replace(/^\s+|\s+$/, "")); c = unescape(c); // 解码cookie值 if (!/\,/.test(c)) { // 判断是否包含"," 如果没有 则表示只包含一个子cookie信息 o[b[0]] = b[1]; } else { var d = c.split(","); for (var j = 0; j < d.length; j++) { var e = d[j].split(":"); o[e[0]] = e[1]; // 把子cookie信息写入返回对象中去 } } } return o; }
测试数据
// 定义expires有效期
// 实验数据 "user=escape(a); expires=d"
var d = new Date();
d.setMonth(d.getMonth() + 1);
d = d.toUTCString();
var a = "name:a, age:20, addr:beijing";
var c = "user=" + escape(a); // escape() 编码
c = c + ";" + "expires=" + escape(d);
document.cookie = c; // 写入cookie信息
if (navigator.cookieEnabled) {
var o = getSubCookie();
console.log(o);
}
封装cookie应用接口
- 传入一个参数时, 表示读取指定的cookie的值
- 传入两个参数时, 表示写入cookie信息, 第一个参数表示名称,第二个参数表示值
第三个参数传递选项信息,对象
function cookie(name, value, options) { if (typeof value != "undefined") { // 如果第二个参数存在 options = options || {}; if (value === null) { options.expires = -1; // 设置失效时间 } var expires = ""; if (options.expires && (typeof options.expires == "number" || options.expires.toUTCString)) { var date; if (typeof options.expires == "number") { date = new Date(); date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); } else { date = options.expires; } expires = "; + expires=" + date.toUTCString(); } var path = options.path ? "; path=" + options.path : ""; // 设置路径 var domain = options.domain ? "; domain=" + options.domain : ""; // 设置域 var secure = options.secure ? "; secure=" + options.secure : ""; // 设置安全措施,为ture则直接设置 document.cookie = [name, "=", encodeURIComponent(value), expires, path, domain, secure].join(""); } else { // 如果第二个参数不存在,则表示读取指定cookie信息 var cookieValue = null; if (document.cookie && document.cookie != " ") { var cookie = document.cookie.split(";"); for (var i = 0; i < cookie.length; i++) { var cookie[i] = (cookie[i] || " ").replace(/^\s+|\s+$/, ""); if (cookie[i].slice(0, name.length + 1) == (name + "=")) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; // 返回查找的cookie值 } }
条件预加载
// 兼容事件监听函数
function addHeadler(target, eventType, handler) {
if (target.addEventListener) { // DOM2 Events
addHeadler = function(target, eventType, handler) {
target.addEventListener(eventType, handler, false);
};
} else { // IE
addHeadler = function(target, eventType, handler) {
target.attachEvent("on" + eventType, handler);
};
}
addHeadler(target, eventType, handler);
}
// 条件预加载
var addHeadler = document.body.addEventListener ? function(target, eventType, handler) {
target.addEventListener(eventType, handler, false);
} : function(target, eventType, handler) {
target.attachEvent("on" + eventType, handler);
};
随机加载函数
// Math.random() * Math.random() 随机数接近于0而疏远于1
function updateRandom() {
var p = Math.random(),
n = Math.random() / 4;
if (p < 0.01) {
return 0 + n; // [0, 0.25)
} else if (p < 0.04) {
return 0.25 + n; // [0.25, 0.5)
} else if (p < 0.1) {
return 0.5 + n; // [0.5, 0.75)
} else {
return 0.75 + n; // [0.75, 1)
}
}
var objects = ["登山包", "旅行箱", "移动电源", "不中奖"];
var object = [];
var num = [0, 0, 0, 0];
for (var i = 0; i < 1000; i++) {
var randomIndex = Math.floor(objects.length * updateRandom());
object[i] = objects[randomIndex];
if (object[i] == "登山包") {
num[0]++;
} else if (object[i] == "旅行箱") {
num[1]++;
} else if (object[i] == "移动电源") {
num[2]++;
} else {
num[3]++;
}
}
num; // 输出测试数据
生成工厂函数
function randomInProbability(weights) {
if (arguments.length > 1) {
weights = [].slice.call(arguments);
}
var total, current = 0,
parts = [],
i = 0,
len = weights.length;
total = weights.reduce ? weights.reduce(function(a, b)) {
return a + b;
}): eval(weights.join("+"));
for (; i < len; i++) {
current += weights[i];
parts.push("if(p<", current / total, "return", i / len, "+n");
}
return Function("var p = Math.random(), n = Math.random() / " + len + ";" + parts.join(""));
}
自定义事件
function EventTarget() {
this.handlers = {};
}
EventTarget.prototype = {
constructor: EventTarget,
addHeadler: function(type, handler) {
if (typeof this.handlers[type] == "undefined") {
this.handlers[type] = [];
}
this.handlers[type].push(handler);
},
fire: function(event) {
if (!event.target) {
event.target = this;
}
if (this.handlers[event.type] instanceof Array) {
var handlers = this.handlers[event.type];
for (var i = 0; len = handlers.length; i < len; i++) {
handlers[i](event);
}
}
},
removeHandler: function(type, handler) {
if (this.handlers[type] instanceof Array) {
var handlers = this.handlers[type];
for (var i = 0, len = handlers.length; i < len; i++) {
if (handlers[i] == handler) {
break;
}
}
handlers.slice(i, 1);
}
}
};
function handlerMessage(event) {
alert("Message received: " + event.message);
}
// 创建一个新对象
var target = new EventTarget();
// 添加一个事件处理程序
target.addHeadler("message", handlerMessage);
// 触发事件
target.fire({
type: "message",
message: "Hello world!"
});
// 删除事件处理程序
target.removeHandler("message", handlerMessage);
// 再次, 应没有处理程序
target.fire({
type: "message",
message: "Hello world!"
});
鼠标拖动功能
var drogDrop = function() {
var dragging = null;
function handlerEvent(event) {
// 获取事件和目标
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
// 确定事件类型
switch (event, type) {
case 'mousedown':
if (target.className.indexOf('draggable') > -1) {
dragging = target;
}
break;
case 'mousemove':
if (dragging != null) {
// 指定位置
dragging.style.left = event.clientX + 'px';
dragging.style.top = event.clientY + 'px';
}
break;
case 'mouseup':
dragging = null;
break;
}
}
// 公共接口
return {
enable: function() {
EventUtil.addHeadler(document, 'mousedown', handlerEvent);
EventUtil.addHeadler(document, 'mousemove', handlerEvent);
EventUtil.addHeadler(document, 'mouseup', handlerEvent);
},
disable: function() {
EventUtil.removeHandler(document, 'mousedown', handlerEvent);
EventUtil.removeHandler(document, 'mousemove', handlerEvent);
EventUtil.removeHandler(document, 'mouseup', handlerEvent);
}
};
}();