Home > Enterprise >  Typescript function becoming undefined
Typescript function becoming undefined

Time:06-08

The function binOp runs once when run from expression and then becomes undefined when it is called by term and I just can't figure out why it is happening. sorry for the amount of code but I don't know where to look anymore. Also it is running in a nextjs localhost if that makes an difference

I get the following error:

TypeError: Cannot read properties of undefined (reading 'binOp')

class Parser {
    tokens: Token[]
    tokIdx: number
    currentTok: Token

    constructor(tokens: Token[]) {
        this.tokens = tokens
        this.tokIdx = -1
        this.currentTok = new Token({type:"null"})
        this.advance()
    }

    advance() {
        this.tokIdx  
        if(this.tokIdx < this.tokens.length) {
            this.currentTok = this.tokens[this.tokIdx]
        }

        return this.currentTok
    }
    
    binOp(func:any, ops:string[]) {
        console.log("here")
        let left: any = func()

        while(this.currentTok.type == TT_MUL || this.currentTok.type == TT_DIV) {
            let opTok = this.currentTok
            this.advance()
            let right = func()
            left = new BinOpNode({leftNode:left, opTok:opTok, rightNode:right})
        }

        return left       
    }

    parse() {
        return this.expression()
    }
    
    factor() {
        let tok: Token = this.currentTok

        if(tok.type == TT_INT || tok.type == TT_FLOAT) {
            this.advance()
            return new NumberNode(tok)
        }
    }

    term() {
        return this.binOp(this.factor, [TT_MUL, TT_DIV])
    }

    expression() {
        return this.binOp(this.term, [TT_PLUS, TT_MINUS])
    }
}

ts playground link

CodePudding user response:

TypeError: Cannot read properties of undefined (reading 'binOp')

This error does not mean binOp is undefined. It means the object that is supposed to have that method is undefined. This is a very important difference.


This line:

return this.binOp(this.term, [TT_PLUS, TT_MINUS])

Is not going to work. You can can't break off a class instances methods like this because the value of this is lost.

The value of this is set by how it's called. By default, when you call myObj.method() then this is set to myObj inside the method function.

All instances of a class share methods. So if you get a reference to method as a standalone function, there is no way to know what instance it came from. So this cannot be the instance that you expect.


So when you pass a method of class you either have to use an enclosing function:

return this.binOp(() => this.term(), [TT_PLUS, TT_MINUS])

Or bind the function before you pass it:

return this.binOp(this.term.bind(this), [TT_PLUS, TT_MINUS])

Working example

  • Related