Skip to content

Instantly share code, notes, and snippets.

@luc4leone
Created February 22, 2019 16:27
Show Gist options
  • Save luc4leone/70f09ad4636b37ae7a03b20c2ff88cc3 to your computer and use it in GitHub Desktop.
Save luc4leone/70f09ad4636b37ae7a03b20c2ff88cc3 to your computer and use it in GitHub Desktop.
copyWithin
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