最近写js代码,想用到类似PHP里面的foreach功能,刚开始的封装还需要传入对象类似 foreach(obj,function(k,v){}); ,太麻烦了,想要直接是 obj.foreach(function(k,v){}); 这样。好了直接上相关代码:
/**
* 判断是否是数组
* @param argument
* @param {number|boolean} opt 是否用严格模式
* @return {*}
*/
function is_array(argument, opt) {
if (opt === 1 || opt === true) {
return Object.prototype.toString.call(argument) === "[object Array]";
}
return argument && (typeof argument === "object") && ("length" in argument) && (typeof argument.length === "number");
}
/**
* 判断是否是对象
* @param argument
* @return {*}
*/
function is_object(argument) {
if (argument && (typeof argument === "object") && ("length" in argument)) {
return Object.prototype.toString.call(argument) === "[object Object]";
}
return argument && (typeof argument === "object") && !("length" in argument);
}
/**
* 判断是否是函数
* @param argument
* @return {*|boolean}
*/
function is_function(argument) {
return typeof argument === "function";
}
/**
* 判断是否是字符串
* @param argument
* @return {*|boolean}
*/
function is_string(argument) {
return typeof argument === "string";
}
/**
* 搜索数组中是否存在指定的值
* @param {string} needle
* @param {array} haystack
* @param {boolean} argStrict
* @return {boolean}
*/
function in_array(needle, haystack, argStrict) {
var key = "", strict = !!argStrict;
if (strict) {
for (key in haystack) {
if (haystack[key] === needle) {
return true
}
}
} else {
for (key in haystack) {
if (haystack[key] == needle) {
return true
}
}
}
return false
}
/**
* 设置对象属性不可修改,不可删除,不可枚举等
* @param {Object|Array|function|Storage} obj
* @param {array|object|string} attrList
*/
function attrNotEach(obj, attrList) {
var O = {writable: false, configurable: false, enumerable: false}; //设置对象属性不可修改,不可删除,不可枚举
var list = ["[object Function]", "[object Storage]", "[object Window]"], val;
if (is_object(obj) || is_array(obj) || in_array(Object.prototype.toString.call(obj), list, true)) {
if (is_array(attrList)) {
for (var i = 0, len = attrList.length; i < len; i++) {
val = attrList[i];
is_string(val) && Object.defineProperty(obj, val, O);
}
} else if (is_object(attrList)) {
for (var attr in attrList) {
val = attrList[attr];
is_string(val) && Object.defineProperty(obj, val, O);
is_object(val) && Object.defineProperty(obj, attr, Object.assign({}, O, val));
}
} else {
is_string(attrList) && Object.defineProperty(obj, attrList, O);
}
}
}
/**
* 遍历数组或对象(Object原型链上)
* @param {function} fn 传入两个参数:key,value。返回值为0或false时停止循环遍历
*/
Object.prototype.foreach = function (fn) {
if (typeof fn === "function") {
var rv;
if (is_array(this, 1)) {
for (var i = 0, len = this.length; i < len; i++) {
rv = fn.call(this, i, this[i]);
if (rv === 0 || rv === false) {
break;
}
}
}
if (is_object(this) || is_function(this)) {
for (var attr in this) {
rv = fn.call(this, attr, this[attr]);
if (rv === 0 || rv === false) {
break;
}
}
}
}
};
/**
* 遍历对象属性(对象,数组,函数)
* @param {function} fn
*/
Object.prototype.foreachAll = function (fn) {
if (typeof fn === "function") {
var list = ["[object Storage]", "[object Window]", "[object Function]"], rv;
if (is_object(this) || is_array(this, 1) || is_function(this) || in_array(Object.prototype.toString.call(this), list, true)) {
for (var attr in this) {
rv = fn.call(this, attr, this[attr]);
if (rv === 0 || rv === false) {
break;
}
}
}
}
};
/**
* 对象属性监听
* @param {string} key
* @param {function|object} getFun
* @param {function} setFun
*/
Object.prototype.attributeListener = function (key, getFun, setFun) {
if (/^[\S\s]+$/.test(key)) {
var O = {writable: true, configurable: true, enumerable: false, value: this[key]}, tk = "__tempKey__", temp_key = "temp__" + key, temp;
if (!is_object(this[tk])) {
this[tk] = {};
Object.defineProperty(this, tk, {writable: true, configurable: true, enumerable: false});
}
if (is_object(getFun)) {
temp = getFun;
temp.writable && (O.writable = temp.writable);
temp.configurable && (O.configurable = temp.configurable);
temp.enumerable && (O.enumerable = temp.enumerable);
temp.value && (O.value = temp.value);
getFun = temp.get;
setFun = temp.set;
}
var cFn = {
get: function () {
is_function(getFun) && getFun.call(this);
return this[tk][temp_key];
},
set: function (newValue) {
this[tk][temp_key] = newValue;
is_function(setFun) && setFun.call(this, newValue);
}
};
Object.defineProperty(this, key, O);
Object.defineProperty(this, key, cFn);
}
};
(function () {
attrNotEach(Object.prototype, ["foreach", "foreachAll", "attributeListener"]);
}());
foreach和foreachAll使用,如图:
attributeListener 的使用,如图: