Created
February 22, 2019 16:27
-
-
Save luc4leone/70f09ad4636b37ae7a03b20c2ff88cc3 to your computer and use it in GitHub Desktop.
copyWithin
This file contains 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
function copyWithin (array, startPasting, startCopying, endCopying) { | |
/* TYPE ERRORS */ | |
// no arguments passed in | |
if (arguments.length === 0) { | |
throw new TypeError('undefined is not an array'); | |
} | |
// The following is taken from underscore.js. Basically it checks if the length property of arguments[0] is there | |
var shallowProperty = function (key) { | |
return function (obj) { | |
return obj == null ? void 0 : obj[key]; | |
}; | |
}; | |
// in Javascript arrays can't contain more elements than this | |
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; // 9007199254740991 | |
// getLength is a function, because shallowProperty returns a function | |
var getLength = shallowProperty('length'); | |
var isArrayLike = function (collection) { | |
var length = getLength(collection); | |
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; | |
}; | |
// first argument is not an array-like object | |
if (isArrayLike(arguments[0]) === false) { | |
throw new TypeError('value ' + JSON.stringify(arguments[0]) + ', of type ' + typeof arguments[0] + ', is not an array-like object'); | |
} | |
/* CORE LOGIC */ | |
// step 1: get array part beginning and ending index | |
var partFromIndex = getPartStart(); | |
var partToIndex = getPartEnd(); | |
// step 2: get array part | |
var part = copyPart(array, partFromIndex, partToIndex); | |
// step 3: get array beginning and ending paste index | |
var pasteFromIndex = getPasteStart(); | |
var pasteToIndex = getPasteStop(); | |
// step 4: paste part into array | |
pastePart(array, part); | |
// by putting the code into functions I try to make the solution logic clear at first glance, just by reading var and functions name - which I choose carefully | |
function getPartStart () { | |
var from = startCopying || 0; | |
if (from < 0) { | |
from += array.length; | |
} | |
return from; | |
} | |
function getPartEnd () { | |
var to = endCopying || array.length; | |
if (to < 0) { | |
to += array.length; | |
} | |
return to; | |
} | |
function copyPart (array, fromIndex, toIndex) { | |
var arrayPart = []; | |
for (var i = fromIndex; i < toIndex; i++) { | |
// copy also the array holes | |
if (i in array) { | |
arrayPart[arrayPart.length] = array[i]; | |
} else { | |
arrayPart.length++; | |
} | |
} | |
return arrayPart; | |
} | |
function getPasteStart () { | |
if (startPasting < - array.length) { | |
startPasting = 0; | |
} | |
if (startPasting < 0) { | |
startPasting += array.length; | |
} | |
return startPasting; | |
} | |
function getPasteStop () { | |
var PasteStart = getPasteStart(); | |
var PasteStop = Math.min(PasteStart + part.length, array.length); | |
return PasteStop; | |
} | |
function pastePart(array, arrayPart) { | |
var j = 0; | |
for (var i = pasteFromIndex; i < pasteToIndex; i++) { | |
// also paste holes | |
if (j in arrayPart) { | |
array[i] = arrayPart[j]; | |
j++; | |
} else { | |
delete array[i]; | |
j++; | |
} | |
} | |
} | |
return array; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment