I'm aware there have been a few other questions on this topic, but none of them seem to give a conclusive answer.
I'm building a HTML/CSS/JS mobile app, and have been trying the following style of notation to define some classes:
Style A
var Thing = (function ()
{
var _instance;
var _firstName;
var _lastName;
function Thing(firstName, lastName)
{
_instance = this;
_firstName = firstName;
_lastName = lastName;
}
Thing.prototype.getMyName = function ()
{
return _firstName + " " + _lastName;
}
Thing.prototype.speak = function ()
{
return ("My name is " + _instance.getMyName());
}
return Thing;
}());
The advantages of this are:
this
prefix). _instance
variable and therefore avoid ambiguity around the identity of this
. I also gave the following alternatives a try:
Style B
function Thing(firstName, lastName)
{
this._firstName = firstName;
this._lastName = lastName;
}
Thing.prototype.getMyName = function()
{
return this._firstName + " " + this._lastName;
};
Thing.prototype.speak = function()
{
return "My name is " + this.getMyName();
};
Style C
class Thing
{
constructor (firstName, lastName)
{
this._firstName = firstName;
this._lastName = lastName;
}
getMyName ()
{
return this._firstName + " " + this._lastName;
}
speak ()
{
return ("My name is " + this.getMyName());
}
}
But despite their advantages, I have found B and C difficult to work with because of problems associated with the this
keyword; that is, depending on the context of the caller this
can refer to different things within the class methods. Furthermore in both these cases, using an _instance
variable as I have in A is not possible because all members need to prefixed with this.
.
However, as pointed out in the comments, Style A does not work when multiple instances of the class are created.
What's the best way to write such classes but avoid problems with this
?
If you want to avoid prototype methods with late-bound this
at all costs, you can use the following style in ES6:
class Thing {
constructor(firstName, lastName) {
this.getMyName = () => firstName + " " + lastName;
this.speak = () => "My name is " + this.getMyName();
}
}
(you can also use a function
declaration, but the class
has the advantage that it prevents calls without new
automatically)
You are creating a closure and then sharing the closure among instantiated objects by the Thing
constructor. It will not work as intended.
var elton = new Thing("Elton", "Johnnavartangula");
elton.getMyName(); // <- "Elton Johnnavartangula"
var fenry = new Thing("Fenry", "Honda");
elton.speak(); // <- "My name is Fenry Honda"
sharing privates among instantiated objects is another topic and can be done in several ways like in one of my previous answer or like
function Source(){
var priv = "secret";
return {gp : function(){return priv},
sp : function(v){priv = v}
}
}
sharedProto = Source(); // priv is now under closure to be shared
var p1 = Object.create(sharedProto); // sharedProto becomes o1.__proto__
var p2 = Object.create(sharedProto); // sharedProto becomes o2.__proto__
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.