Class keyword in Javascript - javascript

According to this article it should be a Javascript 2.0 way to define class. However, I never saw that in practice. Thus the question. How to use class keyword and what is the difference between Javascript 1.x way of doing things?

I know this is a old post, but as of today i.e with the advent of ECMAScript 6 we can declare javascript classes.
The syntax goes as follows :
class Person{
constructor(name){
this.name = name;
}
printName(){
console.log('Name is '+this.name);
}
}
var john = new Person('John Doe');
john.printName(); // This prints 'Name is John Doe'
A complete guide to this can be found in this post

The reason you never saw the class keyword used in practice is that all the current implementations of JavaScript are 1.x.
JavaScript 2.0 was merged into ECMAScript 4 which was rather unpopular and so never made it into the real world.
So to answer your question, how do you use the class keyword? You can't.

Summary
In ES6 the class keyword was introduced. The class keyword is no more than syntactic sugar on top of the already existing prototypal inheritance pattern. Classes in javascript is basically another way of writing constructor functions which can be used in order to create new object using the new keyword.
Example
class Person {
constructor(name) {
this.name = name;
}
talk() { console.log('hi'); }
}
const me = new Person('Willem');
console.log(typeof Person)
// logs function, Person class is just another constructor function under the hood
console.log(me.__proto__ === Person.prototype)
// logs true, classes just use the same prototypal inheritance pattern which is used by constructor functions.
// An object created with the new keyword gets a __proto__ property on it which is a reference to the prototype property on a constructor function.
In the above sample there can be observed in the first log that classes create from the class keyword actually are functions under the hood.
console.log(typeof Person) // logs 'function'
es6 classes use the same prototypal inheritance pattern which is used by constructor functions. Here is another example to demonstrate this behavior:
class Dog {
constructor (name) {
this.name = name;
}
bark () { console.log('bark') };
}
let doggie = new Dog('fluffy');
doggie.bark(); // logs bark
Dog.prototype.bark = () => console.log('woof');
// changing the prototype of Dog, doggie refers to this with its __proto__ property.
//Therefore doggie bark method has also changed.
doggie.bark(); // logs woof
The takeaway in the above example is that the bark method of any dog instance can be changed at runtime. This is because the bark method of any object created with the Dog class is just referring to this function.

You never saw it in practice because virtually nothing supports JavaScript 2.0. That draft is from a specification that died before being anything other than draft.

You can still build classes in JS of course using prototype!
var foo = function() {
this.hurrah = "yay!";
return this;
}
foo.prototype.doit() {
alert(this.hurrah);
}

If you've a Java or C# background, here's how to define a class in JavaScript
var MyClass = function (f, l){//constructor
//private members
var firstName = f,
lastName = l,
fullName = function () { //fullName is a private function
return firstName + " " + lastName;
};
return {
//public members
getFullName: fullName
};
}
var output = document.getElementById('Output'); //<div id="Output"></div>
var myName = new MyClass("First", "Last");
output.innerHTML = myName.getFullName();

Just to add the ECMA5 way of class making.
Note that it does not have a constructor function this way (but you can trigger an init function if you like)
var Class = {
el: null,
socket: null,
init: function (params) {
if (!(this.el instanceof HTMLElement)) {
throw new Error('Chat room has no DOM element to attach on.');
}
return this.doStuff();
},
doStuff: function (params) {
return this;
}
};
var instanceofClass = Object.create(Class, {
el: {
value: document.body.querySelector('.what ever')
},
someMoreData: {
value: [0,5,7,3]
}
}).init();

Related

Why a function is treated as a class in JavaScript

I'm on "Introducing ES2015" course of Treehouse and the teacher shows this code to illustrate the arrow functions but here he instantiates the function as a class. Can anybody tell me how is it possible?
What I learned about objects is that you need to create a class before to instantiate it or create a literal object which is not this case.
'use strict';
var Person = function(data) {
for (var key in data) {
this[key] = data[key];
}
this.getKeys = () => {
return Object.keys(this);
}
}
var Alena = new Person({ name: 'Alena', role: 'Teacher' });
console.log('Alena\s Keys: ', Alena.getKeys()); // 'this' refers to 'Alena'
var getKeys = Alena.getKeys;
console.log(getKeys());
Everything works but I don't know why.
You should ask yourself one question: What is a class really?
Actually it is just a syntax to compose the following things:
1) A constructor. That is some kind of function, that constructs an instance of the class.
2) methods. They can be called on instances.
Now for the second one, JS has already a great feature to achieve this: Prototypal Inheritance. Objects can inherit other objects, including methods:
const proto = { method() { /*...*/ } };
const instance = Object.create(proto);
instance.method(); // that works, as instance inherits proto
Now we only need constructors, for that we could just call a function after we created an object using the method above:
constructInstance(Object.create(proto));
Now as that is quite a common task (as JS has prototypal inheritance from the beginning), the new operator was added, which basically does all that:
1) It creates an empty object inheriting from .prototype of the function called on.
2) It calls the function itself with this being the object.
3) It gives back that object.
function Person(name) {
this.name = name;
}
Person.prototype.method = function() { /*...*/ };
new Person("Jonas").method();
And there you go, inheritance & constructors without any classes.
Now as that is still no quite beautiful, the class syntax was added, which basically just creates a function with a prototype.

calling prototype methods from javascript constructor

I have the following simple inheritence pattern and I would like to know if it's ok to call methods the way i do from within the constructor function (basically speaking, using this instead of "super prototype".
Parent class, Pet
function Pet(name) {
this.name = name;
this.nickname = name;
this.adopt();
}
Pet.prototype.adopt = function() {
this.nickname = 'Cutty ' + this.name;
}
Pet.prototype.release = function() {
this.nickname = null;
}
Pet.prototype.cuddle = function() {
console.log(this.name + ' is happy');
}
Subclass, Lion
function Lion(name) {
Pet.prototype.constructor.apply(this, arguments); // super(name)
this.cuddle();
this.release();
}
Lion.inherits(Pet);
Lion.prototype.adopt = function() {
// DTTAH
}
Lion.prototype.release = function() {
Pet.prototype.release.call(this);
console.log('Thanks for releasing ' + this.name);
}
inherits helper (polyfills are bad I know)
Function.prototype.inherits = function(Parent) {
function ProtoCopy() {}
ProtoCopy.prototype = Parent.prototype;
this.prototype = new ProtoCopy();
this.prototype.constructor = this;
}
My pets are instantiated like so var lion = new Lion('Simba')
In Lion constructor,
Can I keep using this when calling sub/parent class methods ? Or should I use methods from parent prototype directly ? (like pseudo call to super() or in release())
Reasons why I am asking are:
this substitution at runtime
constructor property not always what we are thinking (from what I read here and there)
I am not sure how these things can influence the resulting object.
Thanks for your enlightenment !
What is the difference between using this.fn() and MyClass.prototype.fn.call(this) in a constructor function?
This is not specific to constructor functions, it's the same in all functions (methods) that are called on instances.
Indeed there's not much difference apart from the character count when this.fn === MyClass.prototype.fn, and they would behave exactly the same. However, this assumption is not always true - this might not inherit from MyClass.prototype directly, but rather be a subclass instance, and that subclass might have overwritten the this.fn method.
So which one is correct? Both, in fact. If you know the difference, you can choose the appropriate one for your case. Other languages have different default expectations here, see also for calling static methods.
Notice that you cannot replace the class reference by this.constructor, which would be overwritten as well. In a reasonable setup1, this.fn() would be always equivalent to this.constructor.prototype.fn.call(this).
This is similar to the reason why super calls must explicitly reference the super class, and not depend on instance properties (such as this.constructor, this.super or anything similar).
1: Where this.fn is a usual method inherited from the prototype, not an own instance-specific one, and where every prototype has the .constructor pointing to the respective constructor whose .prototype it is.
Simplifying the problem, consider the following code in ES6:
class Pet {
constructor (name) {
this.name = name;
this.talk();
}
talk () {
console.log('My name is ' + this.name);
}
}
class Lion extends Pet {
constructor (name) {
super(name);
}
talk () {
super.talk();
console.log('I am a lion.');
}
}
would be equivalent to:
function Pet (name) {
this.name = name;
this.talk();
}
Pet.prototype.talk = function () {
console.log('My name is ' + this.name);
};
function Lion (name) {
Pet.call(this, name);
}
// inheritance:
Lion.prototype = Object.create(Pet.prototype);
Lion.prototype.constructor = Lion;
// override .talk
Lion.prototype.talk = function () {
Pet.prototype.talk.call(this);
console.log('I am a lion');
}
Running new Lion('Bobby') logs:
My name is Bobby
I am a lion
Further reading: http://eli.thegreenplace.net/2013/10/22/classical-inheritance-in-javascript-es5

Javascript inheritance and encapsulation, done efficiently

Coming from a C++ / Objective-C background, I'm trying to learn how to correctly and efficiently reproduce the patterns of inheritance and encapsulation in Javascript. I've done plenty of reading (Crockford etc.) and while there are plenty of examples of how to achieve one or the other, I'm struggling with how to combine them without introducing significant negatives.
At the moment, I have this code:
var BaseClass = (function() {
function doThing() {
console.log("[%s] Base-class's 'doThing'", this.name);
}
function reportThing() {
console.log("[%s] Base-class's 'reportThing'", this.name);
}
return function(name) {
var self = Object.create({});
self.name = name;
self.doThing = doThing;
self.reportThing = reportThing;
return self;
}
}());
var SubClass = (function(base) {
function extraThing() {
console.log("[%s] Sub-class's 'extraThing'", this.name);
}
function doThing() {
console.log("[%s] Sub-class's replacement 'doThing'", this.name);
}
return function(name) {
// Create an instance of the base object, passing our 'name' to it.
var self = Object.create(base(name));
// We need to bind the new method to replace the old
self.doThing = doThing;
self.extraThing = extraThing;
return self;
}
}(BaseClass));
It mostly does what I want:
// Create an instance of the base class and call it's two methods
var base = BaseClass("Bert");
base.doThing(); // "[Bert] Base-class's 'doThing'"
base.reportThing(); // "[Bert] Base-class's 'reportThing'"
var other = BaseClass("Fred");
// Create an instance of the sub-class and call it's three methods (two from the base, one of it's own)
var sub = SubClass("Alfred");
sub.doThing(); // "[Alfred] Sub-class's replacement 'doThing'"
sub.extraThing(); // "[Alfred] Sub-class's 'extraThing'"
sub.reportThing(); // "[Alfred] Base-class's 'reportThing'"
But, there's (at least!) two issues:
I'm not convinced the prototype chain is intact. If I substitute a method in the prototype via one instance of a sub-class, other instances don't see it:
No encapsulation of .name property
I'm replacing the prototype's implementation of a function like this:
Object.getPrototypeOf(oneInstance).reportThing = function() { ... }
otherInstance.reportThing() // Original version is still called
That's perhaps not a significant problem, but it is causing me to doubt my understanding.
Private variables is something I want to implement efficiently though. The module pattern of variable hiding doesn't help here, as it causes function definitions to exist per-object. I'm probably missing a way of combining patterns, so is there a way of achieving private variables without duplicating functions?
This is usually how I tackle inheritance and encapsulation in JavaScript. The defclass function is used to create a new class that doesn't inherit from any other class and the extend function is used to create a new class which extends another class:
var base = new BaseClass("Bert");
base.doThing(); // "Bert BaseClass doThing"
base.reportThing(); // "Bert BaseClass reportThing"
var sub = new SubClass("Alfred");
sub.doThing(); // "Alfred SubClass replacement doThing"
sub.extraThing(); // "Alfred SubClass extraThing"
sub.reportThing(); // "Alfred BaseClass reportThing"
var other = new SubClass("Fred");
SubClass.prototype.reportThing = function () {
console.log(this.name + " SubClass replacement reportThing");
};
other.reportThing(); // Fred SubClass replacement reportThing
<script>
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
function extend(constructor, keys) {
var prototype = Object.create(constructor.prototype);
for (var key in keys) prototype[key] = keys[key];
return defclass(prototype);
}
var BaseClass = defclass({
constructor: function (name) {
this.name = name;
},
doThing: function () {
console.log(this.name + " BaseClass doThing");
},
reportThing: function () {
console.log(this.name + " BaseClass reportThing");
}
});
var SubClass = extend(BaseClass, {
constructor: function (name) {
BaseClass.call(this, name);
},
doThing: function () {
console.log(this.name + " SubClass replacement doThing");
},
extraThing: function () {
console.log(this.name + " SubClass extraThing");
}
});
</script>
Read the following answer to understand how inheritance works in JavaScript:
What are the downsides of defining functions on prototype this way?
It explains the difference between prototypes and constructors. In addition, it also shows how prototypes and classes are isomorphic and how to create “classes” in JavaScript.
Hope that helps.
The simple recipe follows:
function BaseClass(someParams)
{
// Setup the public properties, e.g.
this.name = someParams.name;
}
BaseClass.prototype.someMethod = function(){
// Do something with the public properties
}
Now the inheritance occurs this way
function SubClass(someParams)
{
// Reuse the base class constructor
BaseClass.call(this, someParams);
// Keep initializing stuff that wasn't initialized by the base class
this.anotherProperty= someParams.anotherProperty;
}
// Copy the prototype from the BaseClass
SubClass.prototype = Object.create(BaseClass.prototype);
SubClass.prototype.constructor = SubClass;
// Start extending or overriding stuff
SubClass.prototype.someMethod = function(){
// In case you still wanna have the side effects of the original method
// This is opt-in code so it depends on your scenario.
BaseClass.prototype.someMethod.apply(this, arguments);
// Override the method here
}
Taken from:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
P.S. Object.create may not be supported on all old browsers, but don't worry, there's a polyfill for that in this link. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
If you want to preserve the prototype chain, you must override and use .prototype:
Example:
Main Class:
function BaseClass(){
}
BaseClass.prototype.doThing = function(){...}
SubClass:
function SubClass(){
}
SubClass.prototype= new BaseClass();
SubClass.prototype.extraThing = function(){};
Now, whenever you change extraThing or doThing it gets replaced everywhere.
The name property is accessible as a public variable (it's not static).
If you want it static, you must put it in prototype.
If you want it private, you mast make it function local:
function BaseClass(nameParam){
var name = nameParam;
}
To create an object simply call the function:
var testObj = new BaseClass("test");
testObj.doThing();
If you want to combine private variables with rewritable functions, you might find your answer here. But if you are able to rewrite the function that has access to the private variable, it's not really a private variable anymore.

How to achieve pseudo-classical inheritance right on the class declaration? [duplicate]

This question already has answers here:
How to implement C# access modifiers in javascript?
(5 answers)
Closed 1 year ago.
Note:
As the answers tell, the code proposed in the question does NOT really achieve inheritance(otherwise it becomes an answer rather than a question .. ) due to some issues described in the question and in my comments. It works as expected as a fake of inheritance(and not even prototypal).
Summary
In short, make it as similar as we are writing a general OO language rather than javascript, but keep the inheritance be correct.
The story
Object.create is a good way to achieve prototypal inheritance, but it's a bit confusing to a typed brain and new fans.
There are various ways that we can write javascript code more like we are writing other OO languages with the pseudo-classical pattern. As it's pseudo-classical, we must deal with the underlying prototypal inheritance of javascript correctly.
What I want to find is an approach that the pseudo-classical inheritance can be achieved right on the class declaration. The code for demonstration is put at the rear of the post, it works as expected, however, there are some annoying things:
I cannot get rid of return in the class declaration or the inheritance won't work.
I have no way except pass this in the class declaration to make the returning closure know what is this.
I also want to get rid of function (instance, _super) {, but not yet have a good idea.
The static(own properties) of a class are not inherited.
A solution would be more of some syntactic sugar than the existing frameworks, a good pattern is applicable.
The _extends function:
function _extends(baseType) {
return function (definition) {
var caller=arguments.callee.caller;
var instance=this;
if(!(instance instanceof baseType)) {
(caller.prototype=new baseType()).constructor=caller;
instance=new caller();
}
var _super=function () {
baseType.apply(instance, arguments);
};
definition(instance, _super);
return instance;
};
}
The Abc class:
function Abc(key, value) {
return _extends(Object).call(this, function (instance, _super) {
instance.What=function () {
alert('What');
};
instance.getValue=function () {
return 333+Number(value);
};
instance.Value=instance.getValue();
instance.Key=key;
});
}
The Xyz class:
function Xyz(key, value) {
return _extends(Abc).call(this, function (instance, _super) {
_super(key, value);
instance.That=function () {
alert('That');
};
});
}
Example code:
var x=new Xyz('x', '123');
alert([x.Key, x.Value].join(': ')+'; isAbc: '+(x instanceof Abc));
var y=new Xyz('y', '456');
alert([y.Key, y.Value].join(': ')+'; isAbc: '+(y instanceof Abc));
var it=new Abc('it', '789');
alert([it.Key, it.Value].join(': ')+'; isAbc: '+(it instanceof Abc));
alert([it.Key, it.Value].join(': ')+'; isXyz: '+(it instanceof Xyz));
x.What();
y.That();
it.What();
it.That(); // will throw; it is not Xyz and does not have That method
No. No. No. This won't do. You're doing inheritance in JavaScript all wrong. Your code gives me migraines.
Creating a Pseudo-Classical Inheritance Pattern in JavaScript
If you want something similar to classes in JavaScript then there are a lot of libraries out there which provide it to you. For example using augment you could restructure your code as follows:
var augment = require("augment");
var ABC = augment(Object, function () {
this.constructor = function (key, value) {
this.key = key;
this.value = value;
};
this.what = function () {
alert("what");
};
});
var XYZ = augment(ABC, function (base) {
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
I don't know about you but to me this looks a lot like classical inheritance in C++ or Java. If this solves your problem, great! If is doesn't then continue reading.
Prototype-Class Isomorphism
In a lot of ways prototypes are similar to classes. In fact prototypes and classes are so similar that we can use prototypes to model classes. First let's take a look at how prototypal inheritance really works:
The above picture was taken from the following answer. I suggest you read it carefully. The diagram shows us:
Every constructor has a property called prototype which points to the prototype object of the constructor function.
Every prototype has a property called constructor which points to the constructor function of the prototype object.
We create an instance from a constructor function. However the instance actually inherits from the prototype, not the constructor.
This is very useful information. Traditionally we've always created a constructor function first and then we've set its prototype properties. However this information shows us that we may create a prototype object first and then define the constructor property on it instead.
For example, traditionally we may write:
function ABC(key, value) {
this.key = key;
this.value = value;
}
ABC.prototype.what = function() {
alert("what");
};
However using our newfound knowledge we may write the same thing as:
var ABC = CLASS({
constructor: function (key, value) {
this.key = key;
this.value = value;
},
what: function () {
alert("what");
}
});
function CLASS(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
As you can see encapsulation is easy to achieve in JavaScript. All you need to do is think sideways. Inheritance however is a different issue. You need to do a little more work to achieve inheritance.
Inheritance and Super
Take a look at how augment achieves inheritance:
function augment(body) {
var base = typeof this === "function" ? this.prototype : this;
var prototype = Object.create(base);
body.apply(prototype, arrayFrom(arguments, 1).concat(base));
if (!ownPropertyOf(prototype, "constructor")) return prototype;
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
Notice that the last three lines are the same as that of CLASS from the previous section:
function CLASS(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
This tells us that once we have a prototype object all we need to do is get its constructor property and return it.
The first three lines of augment are used to:
Get the base class prototype.
Create a derived class prototype using Object.create.
Populate the derived class prototype with the specified properties.
That's all that there is to inheritance in JavaScript. If you want to create your own classical inheritance pattern then you should be thinking along the same lines.
Embracing True Prototypal Inheritance
Every JavaScript programmer worth their salt will tell you that prototypal inheritance is better than classical inheritance. Nevertheless newbies who come from a language with classical inheritance always try to implement classical inheritance on top of prototypal inheritance, and they usually fail.
They fail not because it's not possible to implement classical inheritance on top of prototypal inheritance but because to implement classical inheritance on top of prototypal inheritance you first need to understand how true prototypal inheritance works.
However once you understand true prototypal inheritance you'll never want to go back to classical inheritance. I too tried to implement classical inheritance on top of prototypal inheritance as a newbie. Now that I understand how true prototypal inheritance works however I write code like this:
function extend(self, body) {
var base = typeof self === "function" ? self.prototype : self;
var prototype = Object.create(base, {new: {value: create}});
return body.call(prototype, base), prototype;
function create() {
var self = Object.create(prototype);
return prototype.hasOwnProperty("constructor") &&
prototype.constructor.apply(self, arguments), self;
}
}
The above extend function is very similar to augment. However instead of returning the constructor function it returns the prototype object. This is actually a very neat trick which allows static properties to be inherited. You can create a class using extend as follows:
var Abc = extend(Object, function () {
this.constructor = function (key, value) {
this.value = 333 + Number(value);
this.key = key;
};
this.what = function () {
alert("what");
};
});
Inheritance is just as simple:
var Xyz = extend(Abc, function (base) {
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
Remember however that extend does not return the constructor function. It returns the prototype object. This means that you can't use the new keyword to create an instance of the class. Instead you need to use new as a method, as follows:
var x = Xyz.new("x", "123");
var y = Xyz.new("y", "456");
var it = Abc.new("it", "789");
This is actually a good thing. The new keyword is considered harmful and I strongly recommend you to stop using it. For example it's not possible to use apply with the new keyword. However it is possible to use apply with the new method as follows:
var it = Abc.new.apply(null, ["it", "789"]);
Since Abc and Xyz are not constructor functions we can't use instanceof to test whether an object is an instance of Abc or Xyz. However that's not a problem because JavaScript has a method called isPrototypeOf which tests whether an object is a prototype of another object:
alert(x.key + ": " + x.value + "; isAbc: " + Abc.isPrototypeOf(x));
alert(y.key + ": " + y.value + "; isAbc: " + Abc.isPrototypeOf(y));
alert(it.key + ": " + it.value + "; isAbc: " + Abc.isPrototypeOf(it));
alert(it.key + ": " + it.value + "; isXyz: " + Xyz.isPrototypeOf(it));
In fact isPrototypeOf is more powerful than instanceof because it allows us to test whether one class extends another class:
alert(Abc.isPrototypeOf(Xyz)); // true
Besides this minor change everything else works just like it did before:
x.what();
y.that();
it.what();
it.that(); // will throw; it is not Xyz and does not have that method
See the demo for yourself: http://jsfiddle.net/Jee96/
What else does true prototypal inheritance offer? One of the biggest advantages of true prototypal inheritance is that there's no distinction between normal properties and static properties allowing you to write code like this:
var Xyz = extend(Abc, function (base) {
this.empty = this.new();
this.constructor = function (key, value) {
base.constructor.call(this, key, value);
};
this.that = function () {
alert("that");
};
});
Notice that we can create instances of the class from within the class itself by calling this.new. If this.constructor is not yet defined then it returns a new uninitialized instance. Otherwise it returns a new initialized instance.
In addition because Xyz is the prototype object we can access Xyz.empty directly (i.e. empty is a static property of Xyz). This also means that static properties are automatically inherited and are no different from normal properties.
Finally, because the class is accessible from within the class definition as this, you can created nested classes which inherit from the class which they are nested within by using extend as follows:
var ClassA = extend(Object, function () {
var ClassB = extend(this, function () {
// class definition
});
// rest of the class definition
alert(this.isPrototypeOf(ClassB)); // true
});
See the demo for yourself: http://jsfiddle.net/Jee96/1/
There's an exhaustive tutorial on how to do what you're after.
oop-concepts
pseudo-classical-pattern
all-one-constructor-pattern
I know this doesn't answer your question because as far as I know there is no good way to put everything in the function constructor and have it use prototype.
As I've commented; if you have trouble with the JavaScript syntax then typescript could be a good alternative.
Here is a helper function that I use for inheritance and overriding (calling super) using JavaScript (without Object.create)
var goog={};//inherits from closure library base
//http://docs.closure-library.googlecode.com/git/closure_goog_base.js.source.html#line1466
// with modifications for _super
goog.inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
// modified _super
childCtor.prototype._super = parentCtor.prototype;
};
// Parent class dev
var Parent = function(){};
Parent.prototype.sayHi=function(){
console.log("hi from Parent");
}
// end class
// Child class dev
var Child = function(){}
goog.inherits(Child,Parent);
Child.prototype.sayHi=function(){
//_super only works on parent.prototype
//this is where functions are usually defined
//have to add this. to call _super as well
this._super.sayHi();
console.log("hi from Child");
}
// end Child
//code to test
var c = new Child();
c.sayHi();//hi from Parent and hi from Child
Even if you find a way to write helper functions and make JS constructor functions look like Java classes you have to understand prototype.
You can always try jOOP, though it does require jQuery.
https://github.com/KodingSykosis/jOOP
var myClass = $.cls({
main: function() {
$('body').append('My App is loaded <br/>');
}
});
var mySecondClass = $.cls({
main: function() {
this._super();
$('body').append('My Second App is loaded <br/>');
}
}, myClass);
var app = new mySecondClass();
http://jsfiddle.net/kodingsykosis/PrQWu/
I believe you are looking for more functionality than this, but if you want to just inherit a bunch of methods from another class you could do this
http://cdpn.io/Jqhpc
var Parent = function Parent () {
this.fname = 'Bob';
this.lname = 'Jones';
};
Parent.prototype.getFname = function getFname () {
return this.fname;
};
Parent.prototype.getLname = function getLname () {
return this.lname;
};
var Child = function Child () {
this.fname = 'Jim';
};
Child.prototype = Parent.prototype;
var child = new Child();
document.write(child.getFname()); //=> Jim

Class vs. static method in JavaScript

I know this will work:
function Foo() {};
Foo.prototype.talk = function () {
alert('hello~\n');
};
var a = new Foo;
a.talk(); // 'hello~\n'
But if I want to call
Foo.talk() // this will not work
Foo.prototype.talk() // this works correctly
I find some methods to make Foo.talk work,
Foo.__proto__ = Foo.prototype
Foo.talk = Foo.prototype.talk
Are there other ways to do this? I don’t know whether it is right to do so. Do you use class methods or static methods in your JavaScript code?
First off, remember that JavaScript is primarily a prototypal language, rather than a class-based language1. Foo isn't a class, it's a function, which is an object. You can instantiate an object from that function using the new keyword which will allow you to create something similar to a class in a standard OOP language.
I'd suggest ignoring __proto__ most of the time because it has poor cross browser support, and instead focus on learning about how prototype works.
If you have an instance of an object created from a function2 and you access one of its members (methods, attributes, properties, constants etc) in any way, the access will flow down the prototype hierarchy until it either (a) finds the member, or (b) doesn't find another prototype.
The hierarchy starts on the object that was called, and then searches its prototype object. If the prototype object has a prototype, it repeats, if no prototype exists, undefined is returned.
For example:
foo = {bar: 'baz'};
console.log(foo.bar); // logs "baz"
foo = {};
console.log(foo.bar); // logs undefined
function Foo(){}
Foo.prototype = {bar: 'baz'};
f = new Foo();
console.log(f.bar);
// logs "baz" because the object f doesn't have an attribute "bar"
// so it checks the prototype
f.bar = 'buzz';
console.log( f.bar ); // logs "buzz" because f has an attribute "bar" set
It looks to me like you've at least somewhat understood these "basic" parts already, but I need to make them explicit just to be sure.
In JavaScript, everything is an object3.
everything is an object.
function Foo(){} doesn't just define a new function, it defines a new function object that can be accessed using Foo.
This is why you can access Foo's prototype with Foo.prototype.
What you can also do is set more functions on Foo:
Foo.talk = function () {
alert('hello world!');
};
This new function can be accessed using:
Foo.talk();
I hope by now you're noticing a similarity between functions on a function object and a static method.
Think of f = new Foo(); as creating a class instance, Foo.prototype.bar = function(){...} as defining a shared method for the class, and Foo.baz = function(){...} as defining a public static method for the class.
ECMAScript 2015 introduced a variety of syntactic sugar for these sorts of declarations to make them simpler to implement while also being easier to read. The previous example can therefore be written as:
class Foo {
bar() {...}
static baz() {...}
}
which allows bar to be called as:
const f = new Foo()
f.bar()
and baz to be called as:
Foo.baz()
1: class was a "Future Reserved Word" in the ECMAScript 5 specification, but ES6 introduces the ability to define classes using the class keyword.
2: essentially a class instance created by a constructor, but there are many nuanced differences that I don't want to mislead you
3: primitive values—which include undefined, null, booleans, numbers, and strings—aren't technically objects because they're low-level language implementations. Booleans, numbers, and strings still interact with the prototype chain as though they were objects, so for the purposes of this answer, it's easier to consider them "objects" even though they're not quite.
You can achieve it as below:
function Foo() {};
Foo.talk = function() { alert('I am talking.'); };
You can now invoke "talk" function as below:
Foo.talk();
You can do this because in JavaScript, functions are objects as well.
Call a static method from an instance:
function Clazz() {};
Clazz.staticMethod = function() {
alert('STATIC!!!');
};
Clazz.prototype.func = function() {
this.constructor.staticMethod();
}
var obj = new Clazz();
obj.func(); // <- Alert's "STATIC!!!"
Simple Javascript Class Project: https://github.com/reduardo7/sjsClass
Here is a good example to demonstrate how Javascript works with static/instance variables and methods.
function Animal(name) {
Animal.count = Animal.count+1||1;// static variables, use function name "Animal"
this.name = name; //instance variable, using "this"
}
Animal.showCount = function () {//static method
alert(Animal.count)
}
Animal.prototype.showName=function(){//instance method
alert(this.name);
}
var mouse = new Animal("Mickey");
var elephant = new Animal("Haddoop");
Animal.showCount(); // static method, count=2
mouse.showName();//instance method, alert "Mickey"
mouse.showCount();//Error!! mouse.showCount is not a function, which is different from Java
In additions, now it is possible to do with class and static
'use strict'
class Foo {
static talk() {
console.log('talk')
};
speak() {
console.log('speak')
};
};
will give
var a = new Foo();
Foo.talk(); // 'talk'
a.talk(); // err 'is not a function'
a.speak(); // 'speak'
Foo.speak(); // err 'is not a function'
I use namespaces:
var Foo = {
element: document.getElementById("id-here"),
Talk: function(message) {
alert("talking..." + message);
},
ChangeElement: function() {
this.element.style.color = "red";
}
};
And to use it:
Foo.Talk("Testing");
Or
Foo.ChangeElement();
ES6 supports now class & static keywords like a charm :
class Foo {
constructor() {}
talk() {
console.log("i am not static");
}
static saying() {
console.log(this.speech);
}
static get speech() {
return "i am static method";
}
}
If you have to write static methods in ES5 I found a great tutorial for that:
//Constructor
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 ;)");
};
see #https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/
Just additional notes. Using class ES6, When we create static methods..the Javacsript engine set the descriptor attribute a lil bit different from the old-school "static" method
function Car() {
}
Car.brand = function() {
console.log('Honda');
}
console.log(
Object.getOwnPropertyDescriptors(Car)
);
it sets internal attribute (descriptor property) for brand() to
..
brand: [object Object] {
configurable: true,
enumerable: true,
value: ..
writable: true
}
..
compared to
class Car2 {
static brand() {
console.log('Honda');
}
}
console.log(
Object.getOwnPropertyDescriptors(Car2)
);
that sets internal attribute for brand() to
..
brand: [object Object] {
configurable: true,
enumerable: false,
value:..
writable: true
}
..
see that enumerable is set to false for static method in ES6.
it means you cant use the for-in loop to check the object
for (let prop in Car) {
console.log(prop); // brand
}
for (let prop in Car2) {
console.log(prop); // nothing here
}
static method in ES6 is treated like other's class private property (name, length, constructor) except that static method is still writable thus the descriptor writable is set to true { writable: true }. it also means that we can override it
Car2.brand = function() {
console.log('Toyota');
};
console.log(
Car2.brand() // is now changed to toyota
);
When you try to call Foo.talk, the JS tries to search a function talk through __proto__ and, of course, it can't be found.
Foo.__proto__ is Function.prototype.
Static method calls are made directly on the class and are not callable on instances of the class. Static methods are often used to
create utility function
Pretty clear description
Taken Directly from mozilla.org
Foo needs to be bound to your class
Then when you create a new instance you can call myNewInstance.foo()
If you import your class you can call a static method
When i faced such a situation, i have done something like this:
Logger = {
info: function (message, tag) {
var fullMessage = '';
fullMessage = this._getFormatedMessage(message, tag);
if (loggerEnabled) {
console.log(fullMessage);
}
},
warning: function (message, tag) {
var fullMessage = '';
fullMessage = this._getFormatedMessage(message, tag);
if (loggerEnabled) {
console.warn(fullMessage);`enter code here`
}
},
_getFormatedMessage: function () {}
};
so now i can call the info method as
Logger.info("my Msg", "Tag");
In your case, if you want to Foo.talk():
function Foo() {};
// But use Foo.talk would be inefficient
Foo.talk = function () {
alert('hello~\n');
};
Foo.talk(); // 'hello~\n'
But it's an inefficient way to implement, using prototype is better.
Another way, My way is defined as static class:
var Foo = new function() {
this.talk = function () {
alert('hello~\n');
};
};
Foo.talk(); // 'hello~\n'
Above static class doesn't need to use prototype because it will be only constructed once as static usage.
https://github.com/yidas/js-design-patterns/tree/master/class
Javascript has no actual classes rather it uses a system of prototypal inheritance in which objects 'inherit' from other objects via their prototype chain. This is best explained via code itself:
function Foo() {};
// creates a new function object
Foo.prototype.talk = function () {
console.log('hello~\n');
};
// put a new function (object) on the prototype (object) of the Foo function object
var a = new Foo;
// When foo is created using the new keyword it automatically has a reference
// to the prototype property of the Foo function
// We can show this with the following code
console.log(Object.getPrototypeOf(a) === Foo.prototype);
a.talk(); // 'hello~\n'
// When the talk method is invoked it will first look on the object a for the talk method,
// when this is not present it will look on the prototype of a (i.e. Foo.prototype)
// When you want to call
// Foo.talk();
// this will not work because you haven't put the talk() property on the Foo
// function object. Rather it is located on the prototype property of Foo.
// We could make it work like this:
Foo.sayhi = function () {
console.log('hello there');
};
Foo.sayhi();
// This works now. However it will not be present on the prototype chain
// of objects we create out of Foo
There are tree ways methods and properties are implemented on function or class objects, and on they instances.
On the class (or function) itself : Foo.method() or Foo.prop. Those are static methods or properties
On its prototype : Foo.prototype.method() or Foo.prototype.prop. When created, the instances will inherit those object via the prototype witch is {method:function(){...}, prop:...}. So the foo object will receive, as prototype, a copy of the Foo.prototype object.
On the instance itself : the method or property is added to the object itself. foo={method:function(){...}, prop:...}
The this keyword will represent and act differently according to the context. In a static method, it will represent the class itself (witch is after all an instance of Function : class Foo {} is quite equivalent to let Foo = new Function({})
With ECMAScript 2015, that seems well implemented today, it is clearer to see the difference between class (static) methods and properties, instance methods and properties and own methods ans properties. You can thus create three method or properties having the same name, but being different because they apply to different objects, the this keyword, in methods, will apply to, respectively, the class object itself and the instance object, by the prototype or by its own.
class Foo {
constructor(){super();}
static prop = "I am static" // see 1.
static method(str) {alert("static method"+str+" :"+this.prop)} // see 1.
prop="I am of an instance"; // see 2.
method(str) {alert("instance method"+str+" : "+this.prop)} // see 2.
}
var foo= new Foo();
foo.prop = "I am of own"; // see 3.
foo.func = function(str){alert("own method" + str + this.prop)} // see 3.

Categories