Skip to content

Instantly share code, notes, and snippets.

@brettz9
Created January 11, 2016 21:37
Show Gist options
  • Select an option

  • Save brettz9/aa962f46baf4d8d3a77b to your computer and use it in GitHub Desktop.

Select an option

Save brettz9/aa962f46baf4d8d3a77b to your computer and use it in GitHub Desktop.
Property utilities
function getAllPropertyNames(obj) {
var props = [];
do {
Object.getOwnPropertyNames(obj).forEach(function (prop) {
if (props.indexOf(prop) === -1) {
props.push(prop);
}
});
} while (obj = Object.getPrototypeOf(obj));
return props;
}
// Submitted to https://developer.mozilla.org/en-US/docs/Enumerability_and_ownership_of_properties
// Note that this is not the most efficient algorithm for all cases, but useful for a quick demonstration
var SimplePropertyRetriever = {
getOwnEnumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._enumerable); // Or could use for..in filtered with hasOwnProperty or just this: return Object.keys(obj);
},
getOwnNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._notEnumerable);
},
getOwnEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, false, this._enumerableAndNotEnumerable); // Or just use: return Object.getOwnPropertyNames(obj);
},
getPrototypeEnumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._enumerable);
},
getPrototypeNonenumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._notEnumerable);
},
getPrototypeEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, false, true, this._enumerableAndNotEnumerable);
},
getOwnAndPrototypeEnumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._enumerable); // Or could use unfiltered for..in
},
getOwnAndPrototypeNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._notEnumerable);
},
getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
return this._getPropertyNames(obj, true, true, this._enumerableAndNotEnumerable);
},
// Private static property checker callbacks
_enumerable : function (obj, prop) {
return obj.propertyIsEnumerable(prop);
},
_notEnumerable : function (obj, prop) {
return !obj.propertyIsEnumerable(prop);
},
_enumerableAndNotEnumerable : function (obj, prop) {
return true;
},
// Inspired by http://stackoverflow.com/a/8024294/271577
_getPropertyNames : function getAllPropertyNames(obj, iterateSelfBool, iteratePrototypeBool, includePropCb) {
var props = [];
while (obj) {
if (iterateSelfBool) {
Object.getOwnPropertyNames(obj).forEach(function (prop) {
if (props.indexOf(prop) === -1 && includePropCb(obj, prop)) {
props.push(prop);
}
});
}
if (!iteratePrototypeBool) {
break;
}
iterateSelfBool = true;
obj = Object.getPrototypeOf(obj);
};
return props;
}
};
function getNonenumerablePropertyNames(obj) {
var props = [];
do {
Object.getOwnPropertyNames(obj).forEach(function (prop) {
if (props.indexOf(prop) === -1 && !obj.propertyIsEnumerable(prop)) {
props.push(prop);
}
});
} while (obj = Object.getPrototypeOf(obj));
return props;
}
// Credit http://stackoverflow.com/a/8024294/271577
function getAllPropertyNames(obj) {
var props = [];
do {
Object.getOwnPropertyNames(obj).forEach(function (prop) {
if (props.indexOf(prop) === -1) {
props.push(prop);
}
});
} while (obj = Object.getPrototypeOf(obj));
return props;
}
(function () {
// Dependencies: Object.keys, Object.getOwnPropertyNames, Object.hasOwnProperty
/**
// Obtaining Keys/Properties as Array
Object.keys: direct enumerable
getOwnPropertyNames: direct enumerable and nonenumerable
?: direct nonenumerable
use for-in: direct and indirect enumerable
getAllPropertyNames (custom function): direct and indirect enumerable and nonenumerable
?: direct and indirect nonenumerable
?: indirect enumerable
?: indirect enumerable and nonenumerable
?: indirect nonenumerable
*/
function PropertyRetriever (obj) {
this.obj = obj;
}
PropertyRetriever.prototype.getOwnEnumerables = function () {
var obj = this.obj;
return Object.keys(obj); // Could also use for-in with hasOwnProperty
};
PropertyRetriever.prototype.getOwnNonenumerables = function () {
var obj = this.obj;
return Object.getOwnPropertyNames(obj).reduce(function (prev, prop) {
if (prev.indexOf(prop) === -1 && !obj.propertyIsEnumerable(prop)) {
prev.push(prop);
}
}, []);
};
PropertyRetriever.prototype.getOwnEnumerablesAndNonenumerables = function () {
var obj = this.obj;
return Object.getOwnPropertyNames(obj);
};
PropertyRetriever.prototype.getPrototypeEnumerables = function () {
var obj = this.obj;
};
PropertyRetriever.prototype.getPrototypeNonenumerables = function () {
var obj = this.obj;
};
PropertyRetriever.prototype.getPrototypeEnumerablesAndNonenumerables = function () {
var obj = this.obj;
};
PropertyRetriever.prototype.getOwnAndPrototypeEnumerables = function () {
var obj = this.obj;
};
PropertyRetriever.prototype.getOwnAndPrototypeNonenumerables = function () {
var obj = this.obj;
};
PropertyRetriever.prototype.getOwnAndPrototypeEnumerablesAndNonenumerables = function () {
var obj = this.obj;
};
/*
// Enumeration
use Object.keys: direct enumerable
use getOwnPropertyNames: direct enumerable and nonenumerable
?: direct nonenumerable
for-in: direct and indirect enumerable
use getAllPropertyNames (custom function): direct and indirect enumerable and nonenumerable
?: direct and indirect nonenumerable
?: indirect enumerable
?: indirect enumerable and nonenumerable
?: indirect nonenumerable
*/
function PropertyEnumerator () {
}
PropertyRetriever.prototype.enumerateOwnEnumerables = function (cb) {
var obj = this.obj;
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
cb(obj[prop], prop, obj);
}
}
};
PropertyRetriever.prototype.enumerateOwnNonenumerables = function (cb) {
};
PropertyRetriever.prototype.enumerateOwnEnumerablesAndNonenumerables = function (cb) {
};
PropertyRetriever.prototype.enumeratePrototypeEnumerables = function (cb) {
var obj = this.obj;
for (var prop in obj) {
if (!obj.hasOwnProperty(prop)) {
cb(obj[prop], prop, obj);
}
}
};
PropertyRetriever.prototype.enumeratePrototypeNonenumerables = function (cb) {
};
PropertyRetriever.prototype.enumeratePrototypeEnumerablesAndNonenumerables = function (cb) {
};
PropertyRetriever.prototype.enumerateOwnAndPrototypeEnumerables = function (cb) {
var obj = this.obj;
for (var prop in obj) {
cb(obj[prop], prop, obj);
}
};
PropertyRetriever.prototype.enumerateOwnAndPrototypeNonenumerables = function (cb) {
};
PropertyRetriever.prototype.enumerateOwnAndPrototypeEnumerablesAndNonenumerables = function (cb) {
};
// MULTIPLE-INHERITING CLASS (PropertyEnumerator AND PropertyRetriever)
function PropertyEnumeratorRetriever () {
}
PropertyEnumeratorRetriever.prototype = new PropertyEnumerator;
for (var method in PropertyRetriever.prototype) {
PropertyEnumeratorRetriever.prototype[method] = PropertyRetriever.prototype[method];
}
// EXPORTS
this.PropertyRetriever = PropertyRetriever;
this.PropertyEnumerator = PropertyEnumerator;
this.PropertyEnumeratorRetriever = PropertyEnumeratorRetriever;
}());
// Could implement other Array methods, like some(), filter(), etc.
function PropertyMapper () {
}
PropertyMapper.prototype.mapOwnEnumerables = function (cb) {
};
PropertyMapper.prototype.mapOwnNonenumerables = function (cb) {
};
PropertyMapper.prototype.mapOwnEnumerablesAndNonenumerables = function (cb) {
};
PropertyMapper.prototype.mapPrototypeEnumerables = function (cb) {
};
PropertyMapper.prototype.mapPrototypeNonenumerables = function (cb) {
};
PropertyMapper.prototype.mapPrototypeEnumerablesAndNonenumerables = function (cb) {
};
PropertyMapper.prototype.mapOwnAndPrototypeEnumerables = function (cb) {
var obj = this.obj;
var ret = [];
for (var prop in obj) {
ret.push(cb(obj[prop], prop, obj));
}
return ret;
};
PropertyMapper.prototype.mapOwnAndPrototypeNonenumerables = function (cb) {
};
PropertyMapper.prototype.mapOwnAndPrototypeEnumerablesAndNonenumerables = function (cb) {
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment