arraystypescriptthisclass-members

Why is this array that I populate in the constructor not populated after the constructor returns?


I want to output an array of random values, and array of factorials.

abstract class AClass {

    Numbers: Array<number>;
    NumbersFact: Array<number>;

    constructor(Numbers: Array<number>, NumbersFact: Array<number>) {

        this.Numbers = Numbers;
        this.NumbersFact = NumbersFact;

        for (var i = 0; i < 10; ++i) Numbers[i] = i;

        Numbers = this.fill(Numbers);
        NumbersFact = this.factorial(Numbers);

        console.log(Numbers);
        console.log(NumbersFact);
    }

Everything works. console.log showed two arrays

    fill(array: number[]): number[] {

        // Add random numbers to [Numbers]
        var tmp: number, current: number, top = array.length;
        if (top) while (--top) {
            current = Math.floor(Math.random() * (top + 1));
            tmp = array[current];
            array[current] = array[top];
            array[top] = tmp;
        }
        return array;
    }

First array with random values from 0 to 9

    factorial(array: Array<number>): Array<number> {
        // Create factorial's array from [Numbers].
        var arrayFact = [];
        for (var i = 0; i < array.length; ++i) {
            const fact = (x: number) => {
                return (x == 0) ? 1 : x * fact(x - 1);
            }

            arrayFact.push(fact(array[i]));
        }

        return arrayFact
    }

Second array with with factorial values from first array

    abstract sort(): void;
}

class Class1 extends AClass {
    sort(): void { }
}

var test = new Class1([], []);

console.log(test);
console.log(test.Numbers);
console.log(test.NumbersFact);

Result

console.log in the constructor:

consol.log at the end of the code:

Why is the second array empty?


Solution

  • Because

    NumbersFact = this.factorial(Numbers);
    

    assigns the result of the function call to the NumbersFact method parameter, not to this.NumbersFact.

    The reason

    Numbers = this.fill(Numbers);
    

    seemed to do the right thing is because unlike the factorial method, fill modifies the empty array you passed in as an arg. You had earlier assigned that array to this.Numbers:

    this.Numbers = Numbers;  // assigned an empty array that gets updated later in the ctor
    this.NumbersFact = NumbersFact; // assigned an empty array that stays empty
    

    The return value of fill also got assigned to a method parameter, not to the this.Numbers.

    In other words, the first array was not empty for the wrong reasons.

    Lessons to take away:

    1. Your array methods should either modify their inputs and return void, or they should return new arrays and leave their inputs untouched.

      The only exception to this rule is if you are creating chainable methods/functions.

    2. Understand that array variables are references, like object variables. They don't hold the actual array.