The question is published on by Tutorial Guruji team.
I need to take all elements of given type from an array, like this [{ a: 'a' }, 4, /a-z/, 6, [1, 2, 3], i=>i]
, and when I provide type Number as argument to ofType(type) it returns [ ] :
Array.prototype.ofType = function (type) { let newArr = []; this.forEach(i => i instanceof type ? newArr.push(i) : newArr ); return newArr }
in other cases , like [{ a: 'a' }, 4, /a-z/, 6, [1, 2, 3], i=>i].ofType(RegExp)
it works correctly.
Answer
JavaScript has number primitives and Number objects. A number primitive isn’t instanceof
anything because it isn’t an object, and only objects are “instances” of something (“instance” being a term of art from object oriented programming); so instanceof
is not useful for primitives.
That’s where typeof
comes in. The result of typeof
for primitive numbers is "number"
.
Since instanceof
expects a constructor function as the right hand operand, you could have your ofType
function branch based on whether it gets a function or a string, using instanceof
if it’s a function and typeof
if it’s a string. Using your forEach
loop:
Array.prototype.ofType = function (type) { let newArr = []; if (typeof type === "string") { this.forEach(i => typeof i === type ? newArr.push(i) : newArr ); } else { this.forEach(i => i instanceof type ? newArr.push(i) : newArr ); } return newArr; };
But I wouldn’t use forEach
for this, I’d use filter
:
Array.prototype.ofType = function (type) { let newArr; if (typeof type === "string") { newArr = this.filter(i => typeof i === type); } else { newArr = this.filter(i => i instanceof type); } return newArr; };
Also, I strongly recommend not adding enumerable properties to Array.prototype
, it breaks code that incorrectly uses for-in
loops on arrays. Use Object.defineProperty
instead:
Object.defineProperty(Array.prototype, "ofType", { value(type) { let newArr; if (typeof type === "string") { newArr = this.filter(i => typeof i === type); } else { newArr = this.filter(i => i instanceof type); } return newArr; }, writable: true, configurable: true, enumerable: false // This is the default, so you could leave it off });
Live Example:
Object.defineProperty(Array.prototype, "ofType", { value(type) { let newArr; if (typeof type === "string") { newArr = this.filter(i => typeof i === type); } else { newArr = this.filter(i => i instanceof type); } return newArr; }, writable: true, configurable: true, enumerable: false // This is the default, so you could leave it off }); console.log([1, "2", 3, "4"].ofType("number")); console.log([new Date, "2", new Date, "4"].ofType(Date));