Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Introducing ES2015 Classes Static Methods

Static Methods video seems misleading for beginning learners

This video illustrates a static method in an ES6 class, but it seems confused about the purpose of static methods and this might leave beginners confused and ill-advised.

Essentially, a static method is shoehorned into acting like an instance method using the traditional Function.prototype.call mechanism (which seems like a more advanced technique than the rest of this course uses). At least while performing a bad practice like this, mention that good design would make changeColor an instance method.

But even better, why not show an example or two of how you might really use static methods (e.g. utility functions) and how the "this" keyword inside static methods binds to the class object (Bird) rather than a class instance.

Chris Collier
Chris Collier
17,774 Points

I couldn't agree more. If I didn't have prior experience with static methods in other languages, I would be totally lost as to why static methods exist.

2 Answers

I agree with this. My suggestion is that someone should review the material more properly from a "keep it simple" perspective to catch this type of imo teaching flaws. Always prioritize teaching the main topic!

Sometimes ofc it's useful to have the student think a bit more, so it's just the context that makes this bad. Put that in suggested additional videos/advanced material instead to avoid ruining the pace and cause frustration unnecessarily.

var Person = function (name, age){
    //private properties
    var priv = {};

    //Public properties
    this.name = name;
    this.age = age;

    //Public methods
    this.sayHi = function(){
        alert('hello');
    }
}

// A static method; this method only 
// exists on the class and doesn't exist 
// on child objects
Person.sayName = function() {
    alert("I am a Person object ;)");  
};

// An instance method; 
// All Person objects will have this method
Person.prototype.setName = function(nameIn) {
    this.name = nameIn;  
}

// Tests
var per = new Person('John Doe', 22);

//Shows alert
Person.sayName();

//TypeError: Object [object Object] has no method 'sayName'
per.sayName()

//Show alert
per.sayHi();

//John Doe
per.name;

//22
per.age;

per.setName('Jane Doe');

//Jane Doe
per.name;

An interesting example of the pre-ES6 techniques for implementing class-like behavior.

A good exercise would be to modernize and clean up this code: convert alert to console.log, convert Person to ES6 class, do something useful with the static method, get rid of unused code, etc

NOTE: the this.sayHi method defined in the Person constructor function creates a distinct function object for each Person object that is instantiated, unlike the setName instance method defined on Person.prototype which is shared among all the instances.

Normally we'd prefer this.sayHi to be a regular instance method defined on Person.prototype.

FILE: test1.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Izzy Example</title>
  </head>
  <body>
      <p>See the Console in the Developer Tools to read the console.log output</p>
      <script src="test1.js"></script>
  </body>
</html>

FILE: test1.js

var Person = function (name, age){
    //Public properties
    this.name = name;
    this.age = age;
    this.sayHi = function() {
        console.log(`[Person].sayHi: name=${this.name}, age=${this.age}`);
    };
    console.log(`[Person] constructor: name=${this.name}, age=${this.age}`);
}

Person.prototype.setName = function(nameIn) {
    console.log(`[Person].setName: changed this.name from=${this.name}, to=${nameIn}`);
    this.name = nameIn;
};

// Tests
var p1 = new Person('John Doe', 22);
p1.sayHi();

let p2 = new Person('Janet Doe', 42);
p2.sayHi();

console.log(`p1.sayHi === p2.sayHi: ${p1.sayHi === p2.sayHi}`);

p1.setName('Jim Doe');
p1.sayHi();

p2.setName("Julie Doe");
p2.sayHi();

console.log(`p1.setName === p2.setName: ${p1.setName === p2.setName}`);

TRANSCRIPT: (FIrefox Developer Edition, 55)

[Person] constructor: name=John Doe, age=22
[Person].sayHi: name=John Doe, age=22
[Person] constructor: name=Janet Doe, age=42
[Person].sayHi: name=Janet Doe, age=42
p1.sayHi === p2.sayHi: false
[Person].setName: changed this.name from=John Doe, to=Jim Doe
[Person].sayHi: name=Jim Doe, age=22
[Person].setName: changed this.name from=Janet Doe, to=Julie Doe
[Person].sayHi: name=Julie Doe, age=42
p1.setName === p2.setName: true