-2

I have a class named Terminal in which I have a function constructor in which i have an anonymous function in which I would like to get access to the output() function in Terminal class. How can I do this?

Using this.output() throws an error. (this.output is not a function)

class Terminal
{
    constructor(contentID, inputID, options)
    {
        if (!contentID || !inputID || !options)
        {
            return false;
        }
        this.cid = contentID;
        this.iid = inputID;
        if (!options['pcName'] || !options['username'])
        {
            return false;
        }
        this.pcname = (options['pcName'].replace('<', '&lt;')).replace('>', '&rt;');
        this.username = options['username'];
        this.version = '0.01';
        // commands
        this.commandsList = [];
        this.commandsList['whoami'] = function(){ Terminal.output('lol') };

        console.log('terminal.js version ' + this.version + ' initializing');
        this.output('ja', true);
        this.output('whoami', true);
        this.output('i dont know bro', false, 'whoami');
    }

    output (text, prefix, cmdName) // cmdName is matters only when prefix is false
    {
        if (this.cid && text)
        {
            if (prefix == true)
            {
                text = this.username + '@' + this.pcname + ':~$ ' + text;
            }
            else if (cmdName)
            {
                text = cmdName + ': ' + text;
            }
            var con = document.getElementById(this.cid);
            con.innerHTML = con.innerHTML + text + '<br>';
        }
    }

    makeCommand (cmd)
    {
        if (cmd && cmd != '' && this.commandsList)
        {
            cmd = (cmd.replace('<', '&lt;')).replace('>', '&rt;');
            if (this.commandsList[cmd])
            {
                console.log('Executing ' + cmd);
                this.commandsList[cmd]();
            }
        }
    }
}
Dante383
  • 35
  • 8
  • this.output(), output() and Terminal.output() - without result. – Dante383 Aug 14 '16 at 22:30
  • http://pastebin.com/95seeX7x It's chaotic but anonymous function which I mean is in line 21 and it is called in 54. – Dante383 Aug 14 '16 at 22:33
  • @Dante383 you have to post that with your question (I did it already for you), we're not wizards. Also, it would be helpful if you paste the error as well. – martriay Aug 14 '16 at 22:36

2 Answers2

1

The problem arises because, unfortunately in js if you define a function inside another function, "this" would not point to the outer scope, it would instead point to the global object, if you are working on a browser "this" will be the "window" object. Consider the following example, the first console.log would print { foo: 'bar', log: [Function] }, it points to the right object, but the second nested function getThis console.log would point to the global object,

var object = {
    foo: 'bar',

    log: function() {
        console.log("this:", this);

        var getThis = function() {
            console.log("this: ", this);
        };

        getThis();
    }
};

object.log();

to avoid this behavior in js

you can declare a variable var self = this; and use that self throughout your code, I would say this is a good practice

var object = {
    foo: 'bar',

    log: function() {
        console.log("this:", this);

        var self = this;
        var getThis = function() {
            console.log("this: ", self);
        };

        getThis();
    }
};

object.log();

or you can bind "this" to the function like

var object = {
    foo: 'bar',

    log: function() {
        console.log("this:", this);

        var getThis = function() {
            console.log("this: ", this);
        }.bind(this);

        getThis();
    }
};

object.log();
David
  • 1,139
  • 3
  • 10
  • 16
0

I am not sure it's the answer, I think you need to define a new variable: that equal to this. Then call the method like so: that.Output()

class Terminal
{
    constructor(contentID, inputID, options)
    {
        if (!contentID || !inputID || !options)
        {
            return false;
        }
        this.cid = contentID;
        this.iid = inputID;
        if (!options['pcName'] || !options['username'])
        {
            return false;
        }
        this.pcname = (options['pcName'].replace('<', '&lt;')).replace('>', '&rt;');
        this.username = options['username'];
        this.version = '0.01';
        // commands
        this.commandsList = [];
        var that = this;
        this.commandsList['whoami'] = function(){ that.output('lol') };
 
        console.log('terminal.js version ' + this.version + ' initializing');
        this.output('ja', true);
        this.output('whoami', true);
        this.output('i dont know bro', false, 'whoami');
    }
   
    output (text, prefix, cmdName) // cmdName is matters only when prefix is false
    {
        if (this.cid && text)
        {
            if (prefix == true)
            {
                text = this.username + '@' + this.pcname + ':~$ ' + text;
            }
            else if (cmdName)
            {
                text = cmdName + ': ' + text;
            }
            var con = document.getElementById(this.cid);
            con.innerHTML = con.innerHTML + text + '<br>';
        }
    }
   
    makeCommand (cmd)
    {
        if (cmd && cmd != '' && this.commandsList)
        {
            cmd = (cmd.replace('<', '&lt;')).replace('>', '&rt;');
            if (this.commandsList[cmd])
            {
                console.log('Executing ' + cmd);
                this.commandsList[cmd]();
            }
        }
    }
}
Ivan
  • 34,531
  • 8
  • 55
  • 100
  • Here a more in depth look at `var that = this` http://stackoverflow.com/questions/4886632/what-does-var-that-this-mean-in-javascript – Ivan Aug 14 '16 at 22:42