简体   繁体   中英

Method on constructor’s prototype throws TypeError when called

I have created a function constructor which returns a new array with given parameters. I am trying to add a custom method sumUp using the prototype property. The function constructor returns the array as expected. But when I call that method it is throwing the error:

TypeError: newArr.sumUp is not a function

 function SurajArray(...array) { let arr = []; for (let i = 0; i < array.length; i++) { arr.push(array[i]); } return arr; } SurajArray.prototype.sumUp = function() { let ans = this.reduce((result, value) => { result = result + value; return result; }, 0); return ans; } let newArr = new SurajArray(1, 2, 3, 4, 5); console.log(newArr); // gives correct array console.log(typeof sumUp); // gives undefined let sum = newArr.sumUp(); // This gives an error console.log(sum);

Your SurajArray function just returns a plain array, which won't use SurajArray.prototype as its prototype, so won't have a sumUp function on it, so the result of calling it (whether via new or otherwise) won't have a sumUp function. (There's also no global sumUp function, so the code looking for one won't find it.)

To correctly subclass an array, use class syntax and extends

 class SurajArray extends Array { sumUp() { let ans = this.reduce((result, value) => { result = result + value; return result; }, 0); return ans; } } const newArr = new SurajArray(1, 2, 3, 4, 5); const sum = newArr.sumUp(); console.log(sum);

Or more simply:

 class SurajArray extends Array { sumUp() { let sum = 0; for (const value of this) { sum += value; } return sum; } } const newArr = new SurajArray(1, 2, 3, 4, 5); const sum = newArr.sumUp(); console.log(sum);


¹ It's also possible, in ES2015 and later, to subclass Array with function syntax and Reflect.construct , but it's simpler with class and if you're going to use new anyway, it makes sense to go with simple. (Prior to ES2015, you couldn't properly subclass Array .) Just for completeness, this is what it looks like:

 // The constructor function SurajArray(...args) { return Reflect.construct(Array, args, SurajArray); } // A correctly-set up `SurajArray.prototype` object SurajArray.prototype = Object.create(Array.prototype); SurajArray.prototype.constructor = SurajArray; // A method -- by default, instance methods should be non-enumerable // as this one is (because the default for the `enumerable` flag is // false) Object.defineProperty(SurajArray.prototype, "sumUp", { value() { let sum = 0; for (const value of this) { sum += value; } return sum; }, configurable: true, writable: true, }); // Usage example const newArr = new SurajArray(1, 2, 3, 4, 5); const sum = newArr.sumUp(); console.log(sum);

(Note that additional methods it defines can't correctly use super , though.)

A constructor does not need a return value. The prototype of a constructor function can be used to manipulate instance values ( this... ). So, the most simple and prototypal translation of your function(s) will be:

 // the constructor function SurajArray(...array) { // assign array to the instance (this) this.arr = array; // if sumUp does not exist in the prototype, create it SurajArray.prototype.sumUp = SurajArray.prototype.sumUp || function() { return this.arr.reduce( (acc, val) => acc + val, 0); // ^ the instance value }; // Note: this is mostly done outside the constructor function, // but this also works } // create 2 instances const sa1 = new SurajArray(21, 23, 45); const sa2 = new SurajArray(300, 17, 98); console.log(sa1.sumUp()); console.log(sa2.sumUp());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM