0

I have a small function to create an object and calculate some properties

function MyArrayObj(array) {
    this.array  = array;
    this.sorted = (function (arr) { return arr.sort(function(a, b) { return a - b }) })([...this.array]);
    this.max    = this.sorted.slice(-1).pop();
    this.min    = this.sorted[0];
    this.sum    = this.sorted.reduce(function(a, b) { return a + b; }, 0);
    this.unique = [...new Set(this.sorted)];
}

the reason I do this is that I want to have everything ready as soon as I create the object.

but I have a question about this.sorted: will it's value be calculated every time it is called? or only once, when the object is created?

PS: should I be doing this? or would it be better to wait until I actually need max, min, etc. and only then get the values?

4
  • 1
    pretty sure since this.max and this.min reference a function, it will be called every time .. i suggest writing a little test to check yourself :) Commented Sep 11, 2018 at 2:28
  • 1
    It's not at all clear why you don't just: this.sorted = [...this.array].sort(function(a, b) { return a - b }). Why the immediately involved functions? Commented Sep 11, 2018 at 2:33
  • 1
    Also, why create a new array just to pop the last value? Why not just return the last element with something like this.sorted[this.sorted.length - 1] Commented Sep 11, 2018 at 2:35
  • thanks for your comments. if you guys don't mind, could you add your answers so i can give the due +1 for your effort? Commented Sep 11, 2018 at 15:05

1 Answer 1

1

sorted here is not a function, but the result of calling the anonymous function function (arr) { return arr.sort(function(a, b) { return a - b }) } with the value [...this.array]. So it is not itself a function that will be called again.

PS: should i be doing this? or would it be better to wait until i actually need max, min, etc. and only then get the values?

That will of course depend upon your application. If you're likely to never need them, then it might make sense to wait. But if you will likely need any of them, especially if you're going to use them more than once, then, since the only expensive operation in there is sorted, which is used in some others anyway, you might as well do it up front. The code is much cleaner this way.

But speaking of clean code... if you don't need the prototype of this object (you're not adding methods to this type, that is), then it might be cleaner to create this with a factory function (and thus skip the new operator.) Here is one version:

const myArrayObj = (array, sorted = [... array].sort()) => ({
  array,
  sorted,
  max: sorted[sorted.length - 1],
  min: sorted[0],
  sum: array.reduce((a, b) => a + b, 0),
  unique: [... new Set(sorted)]
})

If you don't like to have sorted defined that way, then you could make it

const myArrayObj = (array) => { 
  const sorted = [... array].sort())
  return {
    array,
    // ...
  }
}

One other point. If you need sorted for itself, this is fine. But if you want sorted only to get max and min, then there is a real inefficiency in doing an O(n * log(n)) operation to get values which you could collect in O(n) ones. Depending upon your data, this may never be an issue, but it's worth considering.

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

Comments

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.