stevekwan / experiments Goto Github PK
View Code? Open in Web Editor NEWHeavily commented code snippets that aim to teach by example.
Heavily commented code snippets that aim to teach by example.
Thanks for helping educate people on JavaScript. I'm hoping we can improve your explanation in a few areas.
// In more "sane" object-oriented languages, you create a class, you spawn
// objects off of them, and you're done with it. If you need to make a global
// change you do it at the class level, and all instantiated objects pick up
// that change automatically. But JavaScript is NOT a "sane" object-oriented
// language.
Even "sane" OO languages distinguish between an instance variable and a class variable (also known as a static variable). Setting Employee.company
is analogous to setting a static, class variable. It's actually perfectly sane for it to work the way it does, and I suspect not even someone new to JavaScript coming from a classical OOP language would think that a class variable should be available on the instances.
Employee.favoriteFood = "Chicken";
// And this change will NOT be propagated to all instances of Employee,
// because they were already created long ago.
console.log("What's my favorite food?");
console.log(steve.favoriteFood);
This reasoning isn't really right. That instances were already created has nothing to do with it. The only reason favoriteFood
isn't available on the instances is because you set the property as if it were a static, class variable, rather than an instance variable.
// So yes, we removed company from Employee...but we did it AFTER the
// constructor had already been called.
Ditto. "After" has nothing to do with it. You were manipulating a static, class variable, which wouldn't have any effect on the instances, regardless if it happened before or after.
Hi Steve,
First, thank you for the tutorial/hints in javascript/constructor-vs-prototype.html
I did want to point out one thing, though. You basically spend lines 215 to 255 demonstrating why defining this.company
within the Employee
constructor is "the WRONG way to do it," however it seems like you're missing the broader context for that technique.
So, you seem to imply that company
should be a "class" variable, with a single value shared by all instances of Employee
. In that case, yes, declaring Employee.prototype.company
after the definition for Employee
is one way to make that happen.
On the other hand, what about the variables firstName
and lastName
? In the example you add these variables to each of the Employee
objects after they have been instantiated, which indicates that an instance of Employee
may or may NOT have a firstName
or lastName
. Yet, if you wanted to ensure that every Employee
had a firstName
and lastName
, as well as indicate that the value of these variables is independent from one instance to another (i.e. "instance" variables), then using this
to define these vars within the Employee
constructor is the optimal technique:
var Employee = function( firstName, lastName )
{
this.firstName = firstName || "First Name";
this.lastName = lastName || "Last Name";
}
Also, getting back to Employee.prototype.company
, you can use it within the constructor function and still achieve a "class" level variable, the value of which is shared by all instances, as in:
var Employee = function( firstName, lastName )
{
Employee.prototype.company = "EA"; // overwrites prototype 'company' each time constructor is called
this.firstName = firstName || "First Name";
this.lastName = lastName || "Last Name";
}
If you change Employee.prototype.company
after the object has been created, that object's company
will change as well. Unless you specifically assign a value to dude.company
after you instantiate a new Employee
(in this case dude
), that object's company
will be referenced up the prototype chain. So, using the above constructor you can:
var steve = new Employee("Steve", "Kwan");
var andrew = new Employee("Andrew", "Wilson");
console.log( steve.firstName +"\n"+ steve.lastName +"\n"+ steve.company );
console.log( andrew.firstName +"\n"+ andrew.lastName +"\n"+ andrew.company );
Employee.prototype.company = "Electronic Arts";
console.log( steve.firstName +"\n"+ steve.lastName +"\n"+ steve.company );
console.log( andrew.firstName +"\n"+ andrew.lastName +"\n"+ andrew.company );
and see:
Steve
Kwan
EA
Andrew
Wilson
EA
Steve
Kwan
Electronic Arts
Andrew
Wilson
Electronic Arts
The only problem here is that if a new object is created Employee.prototype.company
will be reset to EA. Here's how a way to deal with that:
/* Cont'd */
var Employee = function( firstName, lastName )
{
Employee.prototype.company = Employee.prototype.company || "EA";
this.firstName = firstName || "First Name";
this.lastName = lastName || "Last Name";
}
Employee.prototype.company = "Electronic Arts";
var revlin = new Employee("Revlin", "John");
revlin.company = "N/A"; // change revlin's employer
console.log( revlin.firstName +"\n"+ revlin.lastName +"\n"+ revlin.company );
console.log( steve.firstName +"\n"+ steve.lastName +"\n"+ steve.company );
console.log( andrew.firstName +"\n"+ andrew.lastName +"\n"+ andrew.company );
yielding:
Revlin
John
N/A
Steve
Kwan
Electronic Arts
Andrew
Wilson
Electronic Arts
Additionally, a neat way to add some level of encapsulation to these variables would be to use ES5's property descriptor object, including getters and setters. Just wanted to point that out to you. Again, thank you for the short tutorial, which I'm currently using to wrap my brain around JavaScript "classes"
I was reading through your constructor-vs-prototype thing and was confused by this line:
Employee.company = "Electronic Arts";
Where did this come from? Was it a typo (the next line correctly sets the prototype
)?
If not a typo, it's a bit confusing since you never set any properties on the Employee
function before, and there was never any mention of the assumption that this
inside the Employee
function would reference the function itself (and that isn't how classical OOP works either, not even in Python, except for @classmethod
s). Your only explanation later is that "it didn't work", but there must have been an assumption that it somehow should work in the first place?
Can you please provide a copy of that article? Thanks very much!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.