Is commitment enough to become a smarter coder?

Hehe okay Daddy mtf :stuck_out_tongue:
I am feeling kinds of ways right now with the way you teach. I was wondering how do you get into a smart coding space and could you help me figure out things via 1 on 1 messaging? I am a student who has to really understand something to grasp what I am doing. I just started getting back into coding yesterday.

I think if I commit I could get better.
I appreciate any help you can offer.

Ever played ‘Snakes and Ladders’? Learning anything is a bit like that. Sometimes we climb; sometimes we slip. Eventually we reach the next level. The way I teach is because I’m not a teacher, but a teaching assistant (so to speak). Getting long in the tooth and not as engaged as I used to be.

1 Like

Understood! thank you for the advice!

Something I was struggling with to be honest was creating classes built with constructors()

I understand this part:
Class{
NAME = constructor(_name, info){
// I get confused here
just.name = _name
just.info = info};
console.log(NAME(name))
//should call the name if assigned a name.

Const NewName =

//THEN I GET SOOO LOST NOT SURE HOW TO CODE THIS PART!!! :pensive:

It might help to understand JS classes if we go back to the ES5 vanilla ‘constructor functions’. They can be both hoisted functions (declarations) or unhoisted function expression. Probably the first form we might have been exposed to is the declaration:

function Person (name, age, gender) {
    this.name =  name;
    this.age = age;
    this.gender = gender;
}
var jack = new Person("Jack", 19, "male");
var jane = new Person("Jane", 20, "female");

JavaScript is not a class based language, and follows instead a, prototypal model. In today’s ES6+ the same structure still applies, only supplemented by the newer class model. Both old and new object constructions have a prototype object. We won’t get into this, only relate the old (ES5) with the new (ES6).

Setting the technical background aside, notice that the two instances we declared above are plain objects, but with a distinction, they have a constructor and inherit a prototype from that function.

console.log(typeof jack)  //  object
console.log(typeof jane)  //  object

console.log(jack)  //  {name: 'Jack', age: 19, gender: 'male'}
console.log(jane)  //  {name: 'Jane', age: 20, gender: 'female'}

console.log(jack.constructor) 
/*
Person (name, age, gender) {
    this.name =  name;
    this.age = age;
    this.gender = gender;
}
*/

What separates an ‘instance’ from a plain object is alluded to above. They are both objects, but a plain object has only methods inherited from Object.prototype, whereas a constructor function can introduce custom methods that are exclusive to its instances via its own prototype.

In the context of the prototype, instances have a this object upon which the methods can be executed. Don’t let this verbeage confuse you. A little reading on the older constructor function will soon clear up any mystery.

I’m going to let you review this before going on. Take an hour to do some background reading of the ES5 constructor function, and let me know when you’re caught up with the idea.

Second reply 3 hours later: Still on ES5, let’s add a method to our constructor function.

function Person (name, age, gender) {
  this.name =  name;
  this.age = age;
  this.gender = gender;
  this.print = function () {
    console.log(
    ' Name:\t', this.name, '\n', 'Age:\t', this.age, '\n', 'Gender:', this.gender
    )
  }
}

At this stage we need to recreate our instances since the constructor function was edited and previous instances cannot see the changes (they are still instances of the old constructor).

var jack = new Person("Jack", 19, "male");
var jane = new Person("Jane", 20, "female");

jack.print()
/*
 Name:	 Jack 
 Age:	 19 
 Gender: male
*/

jane.print()
/*
 Name:	 Jane 
 Age:	 20 
 Gender: female
*/

There is another, smarter way to add methods to a constructor, one that can be used by earlier instances that are still in state.

// written as a function expression, for example purposes
var Person = function (name, age, gender) {
  this.name =  name;
  this.age = age;
  this.gender = gender;
}

Having changed the constructor, we need to create our instances, again.

var jack = new Person("Jack", 19, "male");
var jane = new Person("Jane", 20, "female");

At this point they do not have any methods. But what if we insert a new method in the prototype object of our constructor?

Person.prototype.print = function () {
  console.log(
  ' Name:\t', this.name, '\n', 'Age:\t', this.age, '\n', 'Gender:', this.gender
  )
}

Now, without having to create new instances,

jack.print()
/*
 Name:	 Jack 
 Age:	 19 
 Gender: male
*/

jane.print()
/*
 Name:	 Jane 
 Age:	 20 
 Gender: female
*/

Notice that the instances immediately inherited the method from their constructor’s prototype object? That’s cool, and in the day, smart programming that permitted on the fly insertion of new methods that all instances, previous or subsequent have access to.

This is important stuff to know, and continues to have a use in ES6. Remember, it is still a prototypal language, even though now it has class objects and some syntactic sugar. Under the bonnet it is still the same working engine.

Let me know when you have had sufficient time to absorb this older, ‘vanilla’ JS and are ready to go into class objects.

Third reply, some hours later…

class Foo {

}
Foo.prototype.is = x => 'Yup!'
 > a = new Foo()
 > a.is()
<- 'Yup!'
 > 

Let that sink in.

Hope you haven’t given up on this, we’re making progress.

From your above code, let’s write an ES6+ Person class with getters:

class Person {
  constructor(name, age, gender) {
    this._name = name;
    this._age = age;
    this._gender = gender;
  }
  get name () {
    return this._name;
  }
  get age () {
    return this._age;
  }
  get gender () {
    return this._gender;
  }
}

We instantiate the instances the same way we did in the ES5 example above.

const jack = new Person("Jack", 19, "male");
const jane = new Person("Jane", 20, "female");

// implement the getter for NAME

console.log(jack.name)  //  Jack
console.log(jane.name)  //  Jane

Just as above, we can extend our class by adding methods to the prototype:

Person.prototype.print = function () {
  console.log(
  ' Name:\t', this.name, '\n', 'Age:\t', this.age, '\n', 'Gender:', this.gender
  )
}

Note that this implementation makes use of the getters.

jack.print()
 Name:	 Jack 
 Age:	 19 
 Gender: male
jane.print()
 Name:	 Jane 
 Age:	 20 
 Gender: female

Please let us know that you are still interested in this topic. Good help is hard to find. Don’t be wasting our time.

1 Like

You won’t be the first, but you are the last. I’m done.

Actually, I’m not done. I’m perplexed. Why did JS try so hard to pretend to be a class based language when clearly, it is not? Why are teachers so bent on avoiding the whole ‘prototype’ discussion in their classes? Why press for defined methods in the class definition, in the first place? What is to gain?

Getters and setters are a big plus, as they DO extend the class with accessor methods that can obfuscate the real data, and validate inputs that would change the data. The new method syntax is really just a hoax to convince us to write our methods in the class definition. Bollocks to that.

If we look closely, even the constructor function is in the prototype object:

 > jack.constructor.prototype
<- {print: [Object: Function], constructor: [Object: Function]}
 > 

It makes zero sense to write methods in the class definition that are not class methods. All the rest should rightly be assigned to the prototype so that class definitions are lightweight and simple. Constructor, getters, setters, period.

They don’t teach that, though. Wallpaper, all the way.

Apologies for the slow response, I am also balancing some tight situations at home looking after my partner, as well as figuring out a new job…

I believe if I can summarize your incredible help in short I now understand:

Similar to creating a variable the class function is comprised of the element of what the class represents, So Media for example is composed of song, movie, book.

Class Media {
constructor(song, movie, book) //composition of the class… now unlike a variable it contains subclasses in more of a parent child situation.

The next step is to create those super classes after we have clarified how we want Media to work. So if for example we want to embed(not sure on the terminology) this into: this._title = title for the media class when we move into the super class of title for a constructor like movie… If we call console.log(media.title//moviename it will know to search through all the child classes of Media to find what we want to call.

Afterwards we begin to specify the child classes, we can give them their own constructors as a book may need to be comprised of slightly different properties then lets say a CD.

Would this be on the right track Sir?
Thank you!

1 Like

EDIT:

Getters enable us to grab the properties we wish to grab, we can specify the exact property we need if we set a getter or we can specify the change of the property if we utilize the setter to co-ordinate the classes we have created.

To show a full example: I want to code a Dancer Class that is constructed of the following:
Properties (Name, Grade, Style)
All properties have a getter and Style has a setter
Methods include: isPresentInClass (boolean), isInjured (boolean)

To create this I would need to do this I believe:

Class Dancer {
constructor(name, grade, style) {
this._name = name
this._grade = grade
this._style = style
};
get name() {
return this._name;
}
get grade() {
return this._grade;
}
get style {
return this._style;
}

set style (style) {
this.isDancersStyle = this._style;
}
toggleisPresentinClass() {
thisis.isPresentinClass= this.isNotisPresentinClass:;
}
toggleisInjured() {
thisis.isInjured= this.isNotiInjured:;
}

Please let me know if you think I am beginning to comprehend the concept better <3

1 Like

Note that it is never a good idea to have variable names the same as methods. The assignment in your setter is reversed from what it should be:

set style (newStyle) {
    this._style = newStyle;
}

None of those variables exist. They need to be added to the constructor and pre-set.

this.isPresent = false;
this.isInjured = false;

Now the methods will look something like this:

toggleIsPresent () {
    this.isPresent = ! this.isPresent;
}
toggleIsInjured () {
    this.isInjured = ! this.isInjured;
}

How does that work?

a = false
a = ! a
console.log(a)    //  true
a = ! a
console.log(a)    //  false

Expect to muddle through this a while longer, and don’t be impatient. Write simple code that works, and then build upon that.

Thank you I appreciate the feedback!

I will keep working and let you know when I think I have more understanding :slight_smile:

1 Like

Be sure to make good use of the JavaScript Console. In Chrome,

Open a blank window: Type the following in the location bar and Enter:

about:blank

Bookmark it on your bookmark bar. Anytime you want to start the console with a blank page (no HTML, etc. behind it) just open a new tab and click the bookmark.

Ctrl+Shift+j

opens the console. This is an interactive shell that takes commands direct from the prompt.

> 

The response is immediate,

<- 

When you see that in my posts, that is what I’m representing.

The nice thing about the shell is that you can keep a live state even in command mode. Want to test a function? Write it in the console (or paste in from your editor) and Enter it. Now the function exists in the namespace and can be called repeatedly.

Remember the code above where we wrote a class definition, and instantiated two instances, then inserted a method while the two instances were still alive? We can even tweak the function expression we assign and still maintain the live state.

Please ask around about the pros and cons of using the prototype object to insert methods. I’m having a hard time finding any cons. The pros that come to mind are,

  • encourages small, lightweight constructors (class definitions)
  • methods are independent and cannot break the class (???)
  • methods can be inserted dynamically (on the fly)
  • new methods are inherited across all instances, old or new

Note the apparent bias, reason enough for you to ask around and see what kind of answers you get. I’d be excited to hear what you learn from that exercise.

class Dancer {
  constructor(name, grade, style) {
    this._name = name;
    this._grade = grade;
    this._style = style;
  }
  get name () {
    return this._name;
  }
  get grade () {
    return this._grade;
  }
  get style () {
    return this._style;
  }
  set style (newStyle) {
    this._style = newStyle;
  }
}

We can grab that code and paste it into the console. Once we hit Enter, the class definition is in memory and in state. We can define instances with it, until we clear the console.

jane = new Dancer("Jane", 20, "Ballet")
jill = new Dancer("Jill", 21, "Interpretative")

Again, those lines are typed into the command line and entered. Two new instants in state.

Oh wait. I forget to add those two variables. No fear. We can add them as attributes of the, you guessed it, constructor.prototype object.

Dancer.prototype.isPresent = false;
Dancer.prototype.isInjured = false;

Let’s test if our instances inherited these attributes (properties):

jane.isPresent = true;
jill.isInjured = true;

Okay, here we go with the whole shebang.

 > class Dancer {
     constructor(name, grade, style) {
       this._name = name;
       this._grade = grade;
       this._style = style;
     }
     get name () {
       return this._name;
     }
     get grade () {
       return this._grade;
     }
     get style () {
       return this._style;
     }
     set style (newStyle) {
       this._style = newStyle;
     }
   }
<- undefined
 > jane = new Dancer("Jane", 20, "Ballet")
<- Dancer {_name: 'Jane', _grade: 20, _style: 'Ballet'}
 > jill = new Dancer("Jill", 21, "Interpretative")
<- Dancer {_name: 'Jill', _grade: 21, _style: 'Interpretative'}
 > Dancer.prototype.isPresent = false;
<- false
 > Dancer.prototype.isInjured = false;
<- false
 > jane.isPresent = true;
<- true
 > jill.isInjured = true;
<- true
 > Dancer.prototype.status = function () {
       return `Present: ${this.isPresent}\nInjured: ${this.isInjured}`;
   }
<- ƒ () {
       return `Present: ${this.isPresent}\nInjured: ${this.isInjured}`;
   }
 > jane.status
<- ƒ () {
       return `Present: ${this.isPresent}\nInjured: ${this.isInjured}`;
   }
 > jane.status()
   'Present: true\nInjured: false'
 > console.log(jill.status())
   Present: false
   Injured: true
<- undefined
 > 

From what I can tell, we cannot write get or set methods outside of the class definition. This makes sense because they are special methods that are partly in the control of the interpreter. Logically, we have no way to intervene, nor should expect to. It’s a feature of the new Class defined syntax, and outside of the vanilla prototype environment.

Notice that I defined isPresent and isInjured as normal properties. They are not meant to have a getter or setter but be immediately poll responsive in vanilla fashion. They are still instance variables and will always need to be in context for each instance, hence, this.is....

Above I arbitrarily set the two dancers’ status. Let’s see if we can toggle them, in state, as before.

 > Dancer.prototype.notPresent = function () {
     this.isPresent = ! this.isPresent;
   }
<- ƒ () {
     this.isPresent = ! this.isPresent;
   }
 > Dancer.prototype.notInjured = function () {
     this.isInjured = ! this.isInjured;
   }
<- ƒ () {
     this.isInjured = ! this.isInjured;
   }
 > jill.notInjured()
<- undefined    //  no return value as expected
 > jill.status()
<- 'Present: false\nInjured: false'
> 

This is tripping right along. Cool stuff from where I sit, but then I’m just inventing on the fly. Coding is fun, isn’t it? Let’s not forget that cool print method. Try it out and show us your results.

Dancer.prototype.print = function () {
  console.log(
  ' Name:\t', this.name, '\n', 'Age:\t', this.age, '\n', 'Style:', this.style
  )
}

One last go at the whole shebang. Note that everything is pasted in (one command at a time) and the responses given by the console (<- ).

 > class Dancer {
     constructor(name, grade, style) {
       this._name = name;
       this._grade = grade;
       this._style = style;
     }
     get name () {
       return this._name;
     }
     get grade () {
       return this._grade;
     }
     get style () {
       return this._style;
     }
     set style (newStyle) {
       this._style = newStyle;
     }
   }
<- undefined
 > jane = new Dancer("Jane", 3, "Ballet")
<- > Dancer {_name: 'Jane', _grade: 3, _style: 'Ballet'}
 > jill = new Dancer("Jill", 4, "Interpretative")
<- > Dancer {_name: 'Jill', _grade: 4, _style: 'Interpretative'}
 > Dancer.prototype.isPresent = false;
<- false
 > Dancer.prototype.isInjured = false;
<- false
 > Dancer.prototype.status = function () {
       return `Present: ${this.isPresent}
 Injured: ${this.isInjured}`;
   }
<- ƒ () {
       return `Present: ${this.isPresent}
    Injured: ${this.isInjured}`;
      }
 > Dancer.prototype.notIsPresent = function () {
       this.isPresent = ! this.isPresent;
   }
<- ƒ () {
       this.isPresent = ! this.isPresent;
   }
 > Dancer.prototype.notIsInjured = function () {
       this.isInjured = ! this.isInjured;
   }
<- ƒ () {
       this.isInjured = ! this.isInjured;
   }
 > jane.notIsInjured()
<- undefined
 > jill.notIsPresent()
<- undefined
 > Dancer.prototype.print = function () {
    console.log(` Name: ${this.name}
 Grade: ${this.grade}
 Style: ${this.style}
 ${this.status()}`
                )
   }
<- ƒ () {
    console.log(` Name: ${this.name}
    Grade: ${this.grade}
    Style: ${this.style}
    ${this.status()}`
                )
   }
 > jane.print()
    Name: Jane
    Grade: 3
    Style: Ballet
    Present: false
    Injured: true
<- undefined
 > jill.print()
    Name: Jill
    Grade: 4
    Style: Interpretative
    Present: true
    Injured: false
<- undefined

The only thing we haven’t done yet is add more instances. Notice how we were able to extend the prototype object on the fly with real effect?