While learning JavaScript, subtle implementation differences often cause me to approach problems differently.
I’ve learned programming from the vantage point of Ruby where there is a clear built-in method for making a shallow copy of an array.
While learning JavaScript, subtle implementation differences often cause me to approach problems differently. In JS there is no function called clone or dup or even initialize_copycreated exclusively for creating a shallow copy. There are such Ruby methods. Yet, it would be naïve to think there is no such functionality.
I started solving a problem relying on operating on a cloned array. Then I took a different approach since I didn’t immediately discover how to clone the array. After solving the problem with other means I found the needed tool to clone the array. Here’s a brief description of my journey.
The Task
The Launch School curriculum tasked me with creating my own version of the JS unshift function. The intent is to familiarize the student with the implementation of built-in JavaScript functions.
unshift modifies an array by inserting a new value at the beginning of the array. The index of the new value is 0 and that of all other array values 1 more than what they were previously.
var array1 = [1, 2, 3];console.log(array1.unshift(4, 5));
// expected output: 5console.log(array1);
// expected output: Array [4, 5, 1, 2, 3]
The implementation is meant to be done using rudimentary iteration with for. No room for clever solutions. This is not an OO solution, so the new function is invoked with an array argument to be modified and not invoked on an array object itself like in the JS built-in version.
My initial process for implementation was:
Clone the input array
Use bracket notation to make the insertion value the first value of the input array
Iterate over the cloned array
Make each object at iteration the subsequent index of the input array
Return the length of the array
Unfortunately, I was stopped cold at step 1.
Why a Clone?
Because of the concept of variables as pointers, if I simply assigned the original array to a new variable, both variables would point to the same array. Modifying the new variable which stores an array, would modify the original array as well.
var arr = [1, 2, 3];
var arr1 = arr;
arr1[0] = 'New Value';arr1; // ['New Value', 2, 3]
arr; // ['New Value', 2, 3]
A copy allows you to modify an array that holds elements with the same value as the original array without modifying the original array.
I wanted to copy since my original approach meant modifying the first index of the copied array (i.e. index 0) and then iterating over the original array and storying its elements in the subsequent indexes of the copied array.
I didn’t immediately infer how to copy.
So instead, I iterated over the original array and stored the element values in temporary variables and re-assigning at each iteration:
var count = [1, 2, 3];function unshift(arr, insertionValue) {
var currentValue;
var newValue = insertionValue;
var iterations = arr.length;
for (var i = 0; i <= iterations; i += 1) {
currentValue = arr[i];
arr[i] = newValue;
newValue = currentValue;
}
return arr.length;
}
console.log(unshift(count, 0)); // 4
console.log(count); // [ 0, 1, 2, 3 ]
This turns out to more closely mirror the JS function as it returns the original modified array instead of a copy.
The Question Remains, ‘How do I clone?’
Although the problem was solved, what methodology does a JS developer use to get a shallow copy?
A Ruby method by the same name: slice.
A Ruby developer may think of this method when only wanting to copy a portion of the array. However, instead of creating a redundant method that essentially does the same thing by another name, JavaScript provides slice. To get a copy of a portion of an array indicate the starting and ending indices. To copy the whole array, start from index 0.
var arr = [1, 2, 3];
var arr1 = arr.slice(0);
// arr.slice(0, 3) would also work
arr1[0] = 'New Value';arr1;
// ['New Value', 2, 3]
arr;
// [1, 2, 3]
It’s quite effective albeit less intuitive for a Ruby developer.
Idiomatic Ruby v. Well…
Ruby was created with the intent of being simple and easy to read (‘Idiomatic Ruby: writing beautiful code’). It is meant to prioritize developer productivity over language optimization.
JavaScript was initially implemented in 10 days in order to simply provide functionality for scripting in the Browser. It wasn’t necessarily developed for clarity.
Not to say that JavaScript developers don’t readily understand the intent of ‘slicing’ from zero. From one standpoint, ‘Why duplicate the functionality in another function if it already exists?’. Is that not DRY code.
The Ruby rebuttal: it’s clearer. If a method is intended to do only one thing, it’s easier to use out the intent of another developer when reading their code.
Source: medium.com
Comments