迭代器模式
·
Yin灏
/**
* 迭代器模式
* 在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素。
*/
// 迭代器
var Iterator = function (items, container) {
// 获取父容器
var container = (container && document.getElementById(container)) || document;
var items = container.getElementsByTagName(items);
var length = items.length;
var index = 0;
var splice = [].splice; // 缓存原生数组 splice 方法
return {
// 获取第一个元素
first: function () {
index = 0;
return items[index]; // 获取第一个元素
},
// 获取最后一个元素
second: function () {
index = length - 1;
return items[index]; // 获取最后一个元素
},
// 获取前一个元素
pre: function () {
if (--index > 0) {
return items[index];
} else {
index = 0;
return null;
}
},
// 获取后一个元素
next: function () {
if (++index < length) {
return items[index];
} else {
index = length - 1;
return null;
}
},
// 获取某一个元素
get: function (num) {
index = num >= 0 ? num % length : (num % length) + length;
return items[index];
},
// 对每一个元素执行某一个方法
dealEach: function (fn) {
var args = splice.call(arguments, 1);
for (var i = 0; i < args.length; i++) {
fn.apply(items[i], args);
}
},
// 对某一个元素执行某一个方法
dealItem: function (num, fn) {
fn.apply(this.get(num), splice.call(arguments, 2));
},
// 排它方式处理某一个元素
exclusive: function (num, allFn, numFn) {
// 对所有元素执行回调函数
this.dealEach(allFn);
// 如果 num 类型是数组
if (Object.prototype.toString.call(num) === "[object Array]") {
// 遍历数组
for (var i = 0, len = num.length; i < len; i++) {
this.dealItem(num[i], numFn);
}
} else {
// 处理第 num 个元素
this.dealItem(num, numFn);
}
},
};
};
/**
* 小试牛刀
*/
/*
<ul id="container">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
*/
var demo = new Iterator("li", "container");
console.log(demo.first()); // <li>1</li>
console.log(demo.pre()); // null
console.log(demo.next()); // <li>2</li>
console.log(demo.get(2000)); // <li>1</li>
// 处理所有元素
demo.dealEach(
function (text, color) {
this.innerHTML = text; // 设置内容
this.style.background = color; // 设置背景色
},
"test",
"pink"
);
// 排它思想处理第 3 个与第 4 个元素
demo.exclusive(
[2, 3],
function () {
this.innerHTML = "被排除的";
this.style.background = "green";
},
function () {
this.innerHTML = "选中的";
this.style.background = "red";
}
);
/**
* 数组迭代器
*/
var eachArray = function (arr, fn) {
var i = 0,
len = arr.length;
for (; i < len; i++) {
if (fn.call(arr[i], i, arr[i]) === false) {
break;
}
}
};
/**
* 对象迭代器
*/
var eachObject = function (obj, fn) {
for (var i in obj) {
if (fn.call(obj[i], i, obj[i]) === false) {
break;
}
}
};
// 使用迭代器
for (var arr = [], i = 0; i < 5; arr[i++] = i); // 创建数组
eachArray(arr, function (i, data) {
console.log(i, data);
});
/*
0 1
1 2
2 3
3 4
4 5
*/
var obj = {
a: 23,
b: 56,
c: 67,
};
eachObject(obj, function (i, data) {
console.log(i, data);
});
/*
a 23
b 56
c 67
*/
/**
* 同步变量迭代器
*/
// 同步变量
var A = {
// 所有用户共有
common: {},
// 客户端数据
client: {
user: {
username: "雨夜清荷",
uid: "123",
},
},
// 服务端数据
server: {},
};
// 同步变量迭代取值器
var AGetter = function (key) {
if (!A) return undefined;
var result = A;
key = key.split("."); // 解析属性层析顺序
for (var i = 0, len = key.length; i < len; i++) {
// 如果第 i 层属性存在对应值则迭代该属性
if (result[key[i]] !== undefined) {
result = result[key[i]];
} else {
return undefined;
}
}
return result;
};
console.log(AGetter("client.user.username")); // 雨夜清荷
console.log(AGetter("server.lang.local")); // undefined
/**
* 修改或增加一些同步变量属性数据
*/
var ASetter = function (key, val) {
if (!A) return undefined;
var result = A;
key = key.split(".");
for (var i = 0, len = key.length; i < len - 1; i++) {
if (result[key[i]] === undefined) {
result[key[i]] = {};
}
if (!(result[key[i]] instanceof Object)) {
throw new Error("A." + key.splice(0, i + 1).join(".") + " is not Object");
return false;
}
result = result[key[i]];
}
return (result[key[i]] = val);
};
console.log(ASetter("client.module.news.sports", "on")); // on
// 当然对于一些值类型属性的数据进行子属性赋值操作是不允许的
console.log(ASetter("client.user.username.sports", "on")); // Error: A.client.user.username is not Object