0

I am new to JS and was learning classes in JS but I faced an error saying log is not defined. Here is the code:

    class Keyboard {
      log() {
        return true;
      }
    
      print() {
        log() ? "True" : "False";
      }
    }
    
    const mir = new Keyboard();
    mir.print();
Nicolás Alarcón Rapela
  • 2,714
  • 1
  • 18
  • 29
Mirzhal
  • 19
  • 3

2 Answers2

3

You want this.log(). I added the extra console log so you can see the output properly.

class Keyboard {
  log() {
    return true;
  }

  print() {
    console.log(this.log() ? "True" : "False");
  }
}

const mir = new Keyboard();
mir.print();
Andy
  • 61,948
  • 13
  • 68
  • 95
  • why should I use "this" since log() inside class is equivalent to Keyboard.prototype.log(). Just can you explain why use "this" – Mirzhal Aug 17 '19 at 13:24
  • 1
    `this` is determined by how the function/method is called. [This answer should cover a lot your questions.](https://stackoverflow.com/a/28016676/1377002) – Andy Aug 17 '19 at 13:27
  • 1
    @Mirzhal - Also, "since log() inside class is equivalent to Keybord.prototype.log()" is incorrect. `log()` (on its own) within a class is just like `log()` on its own outside a class: An attempt to call an in-scope function called `log` (and there isn't any in your code). JavaScript has no concept of an implied `this.` like (say) Java and C# do. – T.J. Crowder Aug 17 '19 at 13:35
  • @T.J.Crowder, thank you mr.Crowder for your kind comments. Well, in js tutorials I have learned from, they said that methods inside class are put into prototype of a class. That is, class Car{ drive(){}} that drive method is put inside prototype but if we put the method inside constructor then the method will not be put inside prototype. Is that right? – Mirzhal Aug 17 '19 at 14:02
  • @Mirzhal - Yes, non-static methods defined within the class are put on the class's `prototype` object. What I'm saying above is that `log()` (in your `print()` method) tries to use an in-scope identifier, `log`, and call it. That has nothing whatsoever to do with your `log` method. – T.J. Crowder Aug 17 '19 at 14:12
  • @T.J.Crowder, Mr.Crowder, so if we use log() without "this" then by default we will have this code "window.log()" Correct? – Mirzhal Aug 17 '19 at 14:20
  • @Mirzhal - You're close, but not quite, for two reasons. The first is that you may have a non-global in-scope `log` function. The second is that even if `log` is global, there's a difference between `log()` and `window.log()`: With `log()`, in strict mode (which you should be using), in the call to `log`, `this` will be `undefined`; with `window.log()`, it'll be `window`: https://jsfiddle.net/tjcrowder/8fmxsgen/ Normally, `x.m()` calls `m` with `this` set to `x` (unless `x` is a bound func or an arrow func). (In non-strict mode, if `x` is primitive, it's coerced to an object for `this`.) – T.J. Crowder Aug 17 '19 at 16:17
  • 1
    @T.J.Crowder, thank you Mr.Crowder for your kind explanation. :) – Mirzhal Aug 17 '19 at 16:36
2

You have defined log() as part of class Keyboard so it is not available in the gobal namespace. You have to access it through a Keyboard object. If you are accessing it from within another Keyboard function, you can use this

class Keyboard {
  log() {
    return true;
  }

  print() {
    this.log() ? "True" : "False";
  }
}

const mir = new Keyboard();
mir.print();
Omn
  • 2,982
  • 1
  • 26
  • 39
  • thank you for your answer, Is it correct that this keyword refers to Keyboard new Keyboard object when we use new operator? If so then what this refers to in the following code(because we do not use new keyword) class Keyboard extends React.Component { logic() { return false; } render() { return (

    {this.logic() ? "Yeah" : "Nooo"}

    ); } }
    – Mirzhal Aug 17 '19 at 14:12
  • please I really need your help – Mirzhal Aug 17 '19 at 14:20
  • `new` creates an object e.g. `mir`that is an instance of `Keyboard`, with a object like `mir` can you call `log()` via `mir.log`. In the class definition, you can use `this` because those (non-static) functions won't be callable until you use `new` to actually create an instance of that class to call them on – Omn Aug 17 '19 at 14:36
  • thank you for your kind reply, but in this code I do not create new object with new BUT "THIS" refers to Keyword?? How is that possible? class Keyboard extends React.Component { logic() { return false; } render() { return (

    {this.logic() ? "Yeah" : "Nooo"}

    ); } } const box = document.querySelector(".mir"); ReactDOM.render(, box);
    – Mirzhal Aug 17 '19 at 14:42
  • `this` refers to the object that will be created when you use `new` – Omn Aug 17 '19 at 14:44
  • yes yes I know but look at the code above I do not use NEW keyword anywhere. Then what THIS keyword refers to here

    {this.logic() ? "Yeah" : "Nooo"}

    ???
    – Mirzhal Aug 17 '19 at 14:53
  • @Mirzhal - *"in this code I do not create new object with new BUT "THIS" refers to Keyboard?"* No, `this` refers to an *instance* of `Keyboard`, not to `Keyboard`. `this` only refers to `Keyboard` in `static` functions (or if you do something to expressly make that happen). The instance is created by React. Your JSX `` is converted to `React.createElement(Keyboard);`. React uses `new` within `createElement` to create the component instance. So although *you're* not using `new` to create an instance, it is being done. – T.J. Crowder Aug 17 '19 at 16:41
  • @T.J.Crowder, gosh Mr.Crowder, you again saved my day, :D. Thank you again. By the way, sir I have been following your nifty snippets blog for a while. Are you gonna write any new articles this year?:D – Mirzhal Aug 17 '19 at 17:10
  • @Mirzhal - I have to finish the book first. :-) Then I'll probably start a new site/blog rather than continuing with Nifty Snippets (but obviously I'll do an announcement there if I do). – T.J. Crowder Aug 17 '19 at 17:14