Last active
November 22, 2016 20:05
-
-
Save KeithGillette/21df72d67a68c3f7a7af66d1a0b44374 to your computer and use it in GitHub Desktop.
Based on: https://jsfiddle.net/jfallin/qftv1w8s/4/ & http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/#wrappers_direct_property_injection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @description Configures an CreateOverrideableArray generator function returning arrays with provided array methods overriden or added | |
* @param {{ 'functionName': { 'functionToApply': () => any, 'overrideNativeMethod'?: boolean } }} configuration - configuration object | |
* @returns {function: any[]} CreateOverriddenArray - returns an array of provided parameters with array methods configured | |
*/ | |
export function ConfigureOverridableArrayFactory(configuration: {}) { | |
const callingContext = this; | |
const protoIsSupported = { __proto__: [] } instanceof Array; // Test browser for __proto__ property support | |
// save all standard array methods in a list | |
const anArray: any[] = new Array(); | |
let arrayPropertyNameList: string[] = Object.getOwnPropertyNames(Object.getPrototypeOf(anArray)); | |
let arrayMethodList: {} = {}; | |
for (let i = 0; i < arrayPropertyNameList.length; i++) { | |
if (typeof anArray[arrayPropertyNameList[i]] === 'function' && anArray[arrayPropertyNameList[i]] !== 'constructor') { | |
arrayMethodList[arrayPropertyNameList[i]] = anArray[arrayPropertyNameList[i]]; | |
} | |
} | |
/** | |
* @description Array generator function returning arrays with provided array methods overriden or added | |
* @param {...any} arrayElements - optional parameters with which to initialize array prior to application of overridden methods | |
* @returns {any[]} | |
*/ | |
function CreateOverriddenArray(...arrayElements: any[]) { | |
let OverridenArray: any[] = new Array(); // create an array to return whose methods will overridden | |
OverridenArray.push.apply(OverridenArray, arguments); // push any provided arguments onto the array to return | |
if (protoIsSupported) { // Change prototype if supported | |
OverridenArray.__proto__ = CreateOverriddenArray.prototype; | |
} else { // apply override methods supplied by CreateOverrideableArray on the array instance if we can't put them on the prototype | |
for (let propertyName in configuration) { | |
if (arrayPropertyNameList.indexOf(propertyName) !== -1 && configuration[propertyName].overrideNativeMethod) { // override native array method | |
OverridenArray[propertyName] = function () { | |
return configuration[propertyName].functionToApply.apply(callingContext, [propertyName, arguments]); | |
} | |
} else if (arrayPropertyNameList.indexOf(propertyName) !== -1) { // supplement native array method | |
OverridenArray[propertyName] = function () { | |
configuration[propertyName].functionToApply.apply(callingContext, [propertyName, arguments]); | |
return arrayMethodList[propertyName].apply(this, arguments); | |
} | |
} else { // add new array method | |
OverridenArray[propertyName] = function () { | |
return configuration[propertyName].functionToApply.apply(callingContext, [propertyName, arguments]); | |
} | |
} | |
} | |
} | |
return OverridenArray; | |
} | |
if (protoIsSupported) { // if supported, apply override methods supplied by CreateOverrideableArray on prototype for speedier array creation | |
CreateOverriddenArray.prototype = new Array(); | |
for (let propertyName in configuration) { | |
if (arrayPropertyNameList.indexOf(propertyName) !== -1 && configuration[propertyName].overrideNativeMethod) { // override native array method | |
CreateOverriddenArray.prototype[propertyName] = function () { | |
return configuration[propertyName].functionToApply.apply(callingContext, [propertyName, arguments]); | |
} | |
} else if (arrayPropertyNameList.indexOf(propertyName) !== -1) { // supplement native array method | |
CreateOverriddenArray.prototype[propertyName] = function () { | |
configuration[propertyName].functionToApply.apply(callingContext, [propertyName, arguments]); | |
return arrayMethodList[propertyName].apply(this, arguments); | |
} | |
} else { // add new array method | |
CreateOverriddenArray.prototype[propertyName] = function () { | |
return configuration[propertyName].functionToApply.apply(callingContext, [propertyName, arguments]); | |
} | |
} | |
} | |
} | |
return CreateOverriddenArray; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment