Theo Champion
Theo Champion

Reputation: 99

Calling a method from a method error "X is not a function"

I'm new to javascript and I'm doing a little app in react as an exercise but I'm stuck on a weird problem. I'm trying to call a method inside another method of a same class and it doesn't always work.

export class Core {
constructor() {
    this.promptList = ["Are you sure you want to proceed? [Y/n] ",
                        "Enter a username: ",
                        "Enter your email: "];
    this.funcList = [this.proceed,
                    this.validateUser,
                    this.validateEmail];

    this.currentStep = 0;
}

incStep(state) {
    const newState = Object.assign({}, state,
        {prompt: this.promptList[++this.currentStep]});
    return newState;
}

printError(state, error) {
    console.log("error");
    return Object.assign({}, state,
        {history: state.history.concat(error)});
}

proceed(input, state) {
    if (input == "Y")
        return this.incStep(state);
    else if (input == "n")
        return this.printError(state, "ok bye");
    return state;
}

validateUser(input, state) {
    return state;
}

validateEmail(input, state) {
    return state;
}

process(input, currentState) {
    const newState = Object.assign({}, currentState,
        {history: currentState.history.concat(input)});
    return this.funcList[this.currentStep](input, newState);
}

}

In process(), I call a method from the list of function and this works fine but when I try to call incStep() from proceed() an error is thrown

Uncaught TypeError: this.incStep is not a function
at Array.proceed (http://localhost:8080/index_bundle.js:31881:34)
at Core.process (http://localhost:8080/index_bundle.js:31898:42)

I'm guessing that the error is due to the fact that "this" does not refer to the good object but I don't understand exactly why in this case :/

What am I doing wrong here ?

Upvotes: 1

Views: 50

Answers (1)

Shyam Babu
Shyam Babu

Reputation: 1079

your code is failing because of these parts.

this.funcList = [this.proceed,
                this.validateUser,
                this.validateEmail];

you need to remember array is speacial kind of object in js so it is equivalent to

this.functList = {0:refrence of proceed,
                  1:refrence of validateUser,
                  2:refrence of validateEmail,
                  length:3
                  }

When a function is called as a method of an object, it's this is set to the object the method is called on. So when

 this.funcList[this.currentStep](input, newState);

was called and proceed was executed, this belonged to the objet it resides on, which in this case was the funcList array.

proceed(input, state) {
if (input == "Y")
    return this.incStep(state);

hence this call inside proceed refers to the funclist array and not the class and fails.

Using bind to set this is one way to fix this.

this.funcList = [this.proceed.bind(this),
                 this.validateUser.bind(this),
                 this.validateEmail.bind(this)];

Upvotes: 2

Related Questions