0

For an exercise, I have to reproduce the first function from the Underscore.js library.

The code I wrote passes all the tests, except "should work on an arguments object".

I passed these tests:

  • should return an array with the first n elements of the array
  • should return an array with the first element if n is not a number, is zero, or negative
  • should return the entire array if n is > length
  • should return an empty array if array is not an array

I failed this test: should work on an arguments object

_.first = function (array, n) {
  let arr = [];
  if (!Array.isArray(array)) {
    return [];
  } else if (isNaN(n) || n == null || n <= 0) {
    return [array[0]];
  } else {
    for (let i = 0; i < n && i < array.length; i++) {
      arr.push(array[i]);
    }
  }
  return arr;
};

I would be happy to get some guidance to understand why I am failing to pass the arguments object test. Thanks!

Edit: the solution to my problem:

function (array, n) {
  let arr = [];
  if (
    !(
      Array.isArray(array) ||
      Object.prototype.toString.call(array) === "[object Arguments]"
    )
  ) {
    return [];
  }
  if (isNaN(n) || n == null || n <= 0) {
    return [array[0]];
  } else {
    for (let i = 0; i < n && i < array.length; i++) {
      arr.push(array[i]);
    }
  }
  return arr;
};

1 Answer 1

1

The problem with your first function is in your base case wherein you're testing Array.isArray(). The args object is array-like and not array. So you've to factor in that case as well. You can check if the input is an instance of arguments. Something like:


function isArrayLike(obj) {
  // Check if the input is an array or an arguments object
  return Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Arguments]';
}

_.first = function (array, n) {
  let arr = [];
  
  // Check if the input has a length property
  if (!isArrayLike(array)) {
    return [];
  }
// ...rest
};

const _ = {};

function isArrayLike(obj) {
  return Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Arguments]';
}

_.first = function(array, n) {
  let arr = [];

  if (!isArrayLike(array)) {
    return [];
  } else if (isNaN(n) || n == null || n <= 0) {
    return [array[0]];
  } else {
    for (let i = 0; i < n && i < array.length; i++) {
      arr.push(array[i]);
    }
  }

  return arr;
};

function testFirstWithArgs() {
  function testFunc() {
    const result = _.first(arguments, 2);
    return result;
  }

  const expected = [1, 2];
  const actual = testFunc(1, 2, 3, 4, 5);

  if (JSON.stringify(actual) === JSON.stringify(expected)) {
    console.log("PASS");
  } else {
    console.log("FAIL");
  }
}

testFirstWithArgs();

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your help. The problem with this solution, is that it fails the test "should return an empty array if array is not an array". Even when adding ` if (!Array.isArray(array)) { return []; }`to your code snippet I get again "should work on an arguments object".
@Detla888, I have updated the code. Please take a look and let me know if it works
thanks. It works. I just made a small change to have your solution within my function (see my edited post).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.