The function checks whether an array is of a specific type (only contains elements of that type), the types the function accepts for checking is basically all the JavaScript types plus any types that the user may define manually (using a constructor).
What would you do to make the function more sophisticated? What would you remove or add? How would you improve or extend the function?
const checkArrayType = function checkArrayType(arr, type) {
if (!Array.isArray(arr)) {
throw new Error('The argument "arr" must be an array!');
}
else if (type !== null && type !== undefined && typeof type != 'function') {
throw new Error('The argument "type" must be a function, "null", or "undefined"!');
}
// 'null' and 'undefined' require a different check than the main one
if (type === null || type === undefined) {
return arr.every(function(e){
return e === type;
});
}
return arr.every(function(e){
/*
* not using 'instanceof' because it would return 'true'
* for cases like 'subObj instanceof Object'.
* ---------------------------------
* using 'Object(e)' so that the check works for primitives, see:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
*/
return Object.getPrototypeOf(Object(e)) === type.prototype;
});
};
console.log(checkArrayType([1,2,3,4], Number)); // true
console.log(checkArrayType(['hello', 10], String)); // false
console.log(checkArrayType([[1, 2.5], ['a', 'b']], Array)); // true
console.log(checkArrayType([null, null, null, null], null)); // true
console.log(checkArrayType([new String('hello'), new String('world')], Object)); // false
var Foo = function Foo(){};
console.log(checkArrayType([new Foo(), new Foo()], Foo)); // true
console.log(checkArrayType({a: null}, null)); // throws error
console.log(checkArrayType([], 'abc')); // throws error
One more thing, how am I supposed to deal with long comments like the one in this snippet ?
-
1\$\begingroup\$ Maybe an optional parameter that if true will check if an item can be cast to the given type. For example, "1234" isn't a number, but could be cast to one without an error. \$\endgroup\$Ctznkane525– Ctznkane5252018年01月02日 00:56:39 +00:00Commented Jan 2, 2018 at 0:56
-
2\$\begingroup\$ I have rolled back the last edit. Please see What to do when someone answers . \$\endgroup\$Martin R– Martin R2018年01月02日 08:57:23 +00:00Commented Jan 2, 2018 at 8:57
2 Answers 2
The implementation could be written more compactly using arrow functions, for example:
if (type === null || type === undefined) {
return arr.every(e => e === type);
}
return arr.every(e => Object.getPrototypeOf(Object(e)) === type.prototype);
There are two arr.every
calls at different execution paths.
You could eliminate that duplicated logic by extracting the function parameter of arr.every
to a variable:
var checker;
if (type === null || type === undefined) {
checker = e => e === type;
} else {
checker = e => Object.getPrototypeOf(Object(e)) === type.prototype;
}
return arr.every(checker);
-
\$\begingroup\$ Thanks for answering! Why arrow functions if you are not using
this
though ? \$\endgroup\$doubleOrt– doubleOrt2018年01月02日 08:38:28 +00:00Commented Jan 2, 2018 at 8:38 -
1\$\begingroup\$ @Taurus arrow functions are especially appropriate when you're not using
this
. They are best with pure functions with no state. \$\endgroup\$janos– janos2018年01月02日 08:45:22 +00:00Commented Jan 2, 2018 at 8:45 -
\$\begingroup\$ A bit of a general question, don't you think
!==
is more straightforward and readable than===
? I don't know but to my brain it seems that way. \$\endgroup\$doubleOrt– doubleOrt2018年01月02日 08:54:44 +00:00Commented Jan 2, 2018 at 8:54 -
1\$\begingroup\$ @Taurus I've never felt readability issues with these operators. But depending on the conditions used, there are sometimes readability aspects when choosing between some complex condition and its negated version, applying DeMorgan's Law, and arranging
if
andelse
statements. \$\endgroup\$janos– janos2018年01月02日 09:09:23 +00:00Commented Jan 2, 2018 at 9:09
The function does one thing well. I would change nothing. Wait for your calling code to develop a need for fancier functionality, and develop a (related) fancier function then.
The console.log() calls, with comments suggesting true return is expected, would benefit from being placed within a unit test framework.
You asked about the long comment. Delete the "----" ascii art. Prefer full sentences to sentence fragments. And for http://very-very-very-long.com/urls consider introducing them with a bit.ly shortened URL. Then there's something for a person to copy-n-paste / click on, and verify they landed in the expected place, while also giving you the flexibility to line wrap it, and defending against link rot as the months go by.
-
\$\begingroup\$ I thought that was an actual website for a while. How do they protect from link rot though ? \$\endgroup\$doubleOrt– doubleOrt2018年01月01日 21:00:45 +00:00Commented Jan 1, 2018 at 21:00
-
1\$\begingroup\$ Link rot is a fact of life; pages (and sites) go 404 all the time. Half-life is on the order of eight months, with some folks (like NYTimes) being much better at URL-naming and archival storage than other folks. It is the responsibility of a comment's author to protect against link rot, by offering full citation, giving short (convenient, clickable) URL plus full (line wrapped) URL. The trouble with offering just a shortened URL is the target site might delete the page and 301 to another page, rather than correctly 404'ing the deleted page. Your 87-character URL can be hard to linewrap nicely. \$\endgroup\$J_H– J_H2018年01月01日 21:11:16 +00:00Commented Jan 1, 2018 at 21:11