Is init a special reserved keyword for Javascript Object Literals? - javascript

I ran across the following Javascript code.
var Zoo = {
animals: [],
init: function (animal_list) {
for (i = 0; i < animal_list.length; i++) {
this.animals.push(animal_list[i]);
}
}
It looks like the init key maps to an executable function. That function takes in an animal list each item in the list into an animal array.
If I were in my native tongue Ruby, I would do something like this:
class Zoo
def initialize animal_list
#animals = animal_list #animal_list is an array
end
end
So is init the javascript equivalent of an initialize function? In ruby, I can call
my_ruby_zoo = Zoo.new ["lions", "tigers", "bears"]
In javascript, does the init function map to
var my_javascript_zoo = Zoo.new( ["lions", "tigers", "bears"]);

Is init a special reserved keyword for Javascript Object Literals?
No, not at all. There is no pre-named function for initialization in JavaScript. Typically, if you have need of a "class" of objects in JavaScript, you use a constructor function with the new keyword:
function Person(first, last) {
this.first = first;
this.last = last;
}
// Usage:
var chuck = new Person("Charles", "Foreman");
You might then add functions that all instances created via new Person can use, by adding them as properties to the prototype that gets assigned to objects created via new Person (that prototype is taken from the Person.prototype property):
Person.prototype.getFullName = function() {
return this.first + " " + this.last;
};
Because this is a bit long-winded and handling inheritance hierarchies is more effort than it is in other languages (something that's being fixed in ES6), there are a lot of libraries out there that provide helper functions to hook things up for you. (Mine is called Lineage, there's also Resig's Really Simple Inheritance, PrototypeJS's Class, etc.) Some of these helper scripts may give certain function names special meaning. For instance, in both Lineage and PrototypeJS's Class, a function called initialize is special. (I've seen some where ctor was special.)
But not within JavaScript itself.
Your Zoo might look like this:
function Zoo(animal_list) {
this.animals = animal_list.slice(0); // Copy the array
}
If you want to add functions available on all Zoo instances, typically you'd add them to the prototype assigned by new Zoo:
Zoo.prototype.showAll = function() {
this.animals.forEach(function(animal) {
console.log(animal);
});
};
// Usage:
var z = new Zoo(['Tortoise', 'Emu', 'Lion']);
z.showAll();

If you want to make your Zoo class a constructor it should be a function instead of an object literal:
var Zoo = function(animal_list) {
this.animals = [];
for (i = 0; i < animal_list.length; i++) {
this.animals.push(animal_list[i]);
}
}
var myZoo = new Zoo(["lions", "tigers", "bears"]);

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.

Which way to use to define classes in JavaScript

I found different ways that seem to work.
Mostly recommended way in textbooks and the internet:
var Person = function() {
this.age = 23;
}
Tony = new Person();
This also seems to work:
function Person() {
this.age = 23;
}
Tony = new Person();
Is there a difference? And an additional question: Usually you cannot simply leave out parentheses. Here it is possible (new Person instead of new Person()). This is because of using the new keyword, right?
A third odd way that I just tried out looks like this:
function Person() {
return {age: 2};
}
Tony = new Person();
Tony = Person(); // both ways work! It seems that you can leave out 'new' here.
Here I don't get an object with the name of my class, but my property is also accessible and it seems like it was quite similar to both above approaches.
What shall I use and what are the technical differences? Thank you!
JavaScript is a classless language. Classes don't exist, but objects may inherit properties from each other by using prototypes. This means you are not limited to implementing inheritance in a class-like manner. Personally, I like to use a BackboneJS-inspired method (code requires UnderscoreJS):
var BaseObject = function(){}; //Create a function so that we may use the new operator.
//There may be code in the constructor
BaseObject.extend = function(obj) { //Add a static function to the BaseObject to extend it
var base = this; //Save a reference for later
//Create the constructor for the sub object. We need to extend it, so we can't use the base constructor. AFAIK, this is the only way to clone the base constructor, i.e. by creating a new function that calls it
var SubObject = _.extend(function(){
base.apply(this, arguments); //Call base constructor
}, this);
SubObject.prototype= _.extend({}, this.prototype, obj); //Create new prototype that extends the super prototype, but does not overwrite it.
return SubObject; //Return the new constructor + prototype
};
This allows you to do cool class-like stuff like this:
var Car = BaseObject.extend({
speed: 0,
acceleration: 5,
accelerate: function(){
this.speed += this.acceleration;
}
});
var RaceCar = Car.extend({
acceleration: 10,
});
var car = new Car();
var raceCar = new RaceCar();
car.accelerate();
raceCar.accelerate();
if(raceCar.speed > car.speed){
console.log('raceCar won');
}else{
console.log('car won');
}
For more information on inheritance in JavaScript, I strongly recommend reading JavaScript: The Good Parts by Douglas Crockford.
Regarding your examples:
The difference between 1 and 2 is minimal. For more information see this question.
In 3, you are just returning an object literal. The new keyword only has influence on the this keyword within the function, which you are not using, and so using new has no effect. For more information, see this quesion
1 and 2 (var x = function vs function x) are very similar. 3 is a completely different thing.
The difference between 1 and 2 has nothing to do with classes and has been asked before on SO (several times). I think the most complete answer is this one:
https://stackoverflow.com/a/338053/1669279
In short, the first x points to an anonymous function and some debugging tools might have problems with that. The first one is available from the line it was defined on while the second is available in the entire scope. Read the linked answer for details.
The 3rd "solution" is not a class at all. It is simply a function that returns an object (might be called a Factory method).
It is not a good idea to return things from your constructors, especially return this. You should only return things if you want to override the normal process of creating objects (like implementing the singleton pattern for example).
As a side-note, you should always use new when you instantiate a class. Here is what happens when you try to be smart and save characters:
function X () {
return this;
}
console.log(X()); // outputs the window object
The parenthesis after calling the constructor with no parameters are optional, but it is frowned upon to avoid them because it results in slightly more confusing code.
To sum it up, i usually use pattern 1. Pattern 2 is also ok.
One problem with pattern 2 can be this one:
var x = new X(); // works
console.log(x.message); // works, I am X
x.method(); // doesn't work, method hasn't been defined yet
function X() {
this.message = 'I am X';
}
X.prototype.method = function() {
console.log(this.message);
};
this is how i do mine:
;(function (window) {
"use strict";
//-- Private Vars
var opt, obj, rm, Debug;
//-- construtor
function App(requestedMethod) {
//-- set up some vars
if(typeof requestedMethod !== 'undefined') {
rm = requestedMethod;
}
opt = {
rMethod: (typeof rm !== 'undefined') ? (rm != null) ? rm : false : false
}
//-- containe resulable objects
obj = {}
//-- call the init method
this.init();
}
/** Public Methods **/
/**
* The Init method called on every page load
*/
App.prototype.init = function () {
var om = opt.rMethod;
//-- Once all init settings are performed call the requested method if required
if(om) {(typeof App.prototype[om] == 'function') ? App.prototype[om]() : _DB('Call to Method [' + om + '] does not exsist.');}
};
/**
* testmethod
*/
App.prototype.testmethod = function () {
};
/** Private Methods **/
function PrivateMethod(){
}
/**
* A console output that should enable to remain enable js to work in IE
* just incase i forget to remove it when checking on those pesky IE browsers....
*/
function _DB(msg){
if(window.console && window.console.log){
var logDate = new Date();
window.console.log('------------------- ' + logDate + ' ----------------------------------');
window.console.log(msg);
}
};
window.App = App;
})(window);
then call it like:
<script src="ptha/to/your/app.js"></script>
<script>$(function() { new App('testmethod'); });</script>
When the code is loaded the new App() will then run once all page load data has completed
Hope this helps.To get access to it outside add the new to a var
var App = new App('testmethod);
then you can access things like
App.testmethod()...
var Person = function() {
this.age = 23;
}
Person is a variable that contains(is referenced) an anonymous function
function Person() {
this.age = 23;
}
but here you declare a function called "Person"
function Person() {
return {age: 2};
}
and so you declare a function that returns a new static object.
The best way depends on the needs, if you want to declare classes use the second, while to create the modules uses the third. For the first method look here: http://helephant.com/2008/08/23/javascript-anonymous-functions/

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

How to extend a class in JavaScript

I'm working on a chess game built in JavaScript. I'm taking an object-oriented approach to it and am having some difficulty working with JavaScript's inheritance. I want there to be a "Piece" abstract class that holds some fields and basic getters/setters such as is this piece black or white. I then want to have classes for each type of piece that I can instantiate like so:
var pieceOne = new Pawn();
The Pawn() should have all the fields and methods of Piece but have its own method for movement, and additional fields (such as whether or not it has moved yet, as this doesn't matter for most pieces). Here's my current Piece class:
//This object specifies basic information about pieces.
"use strict";
function Piece(color, type, captured, hasMoved) {
this.color = color;
this.type = type;
this.captured = captured;
this.hasMoved = hasMoved;
this.image = color + "_" + type + ".svg";
}
Piece.prototype.getImage = function getImage(){
return this.image;
}
Piece.prototype.isCaptured = function isCaptured(){
return this.captured;
};
I know if I am going to make a subclass for every kind of piece that I'd probably eliminate the "type" field, but how could I make a Pawn subclass? Something like this?
function Pawn() = new Piece(color, captured, hasMoved);
Pawn.prototype.getLegalMoves = function getLegalMoves(){
//return legal moves
}
var pieceOne = new Pawn("black", false, false);
Extending a class can be done in different ways. The simplest method to extend an class is to use Object.create method. This is common method which is used to achieve abstraction (Link to my blog). Let's give an example of the Object.create method as follows.
var Logger = { log : function(log){} }
var ConsoleLogger = function() {};
ConsoleLogger.prototype = Object.create(Logger);
If you are willing to take an object oriented approach on JS I would recommend you to follow the power constructor pattern.
Basically you have a function that creates objects for you and take advantage of the closures to hide the internal properties (fields or methods).
function myObject(){
var that={};
var myPrivateField;
var myPrivateFunction=function(){
}
that.myPublicMethod=function(){
}
return that;
}
Then you can just call the method myObject() and you will get a new object of this type.
You can extend this example to use inheritance by just calling the power constructor of another object and then use object augmentation. Take a look at the example of parasatic inheritance of Douglas Crockford.
You can call Piece's constructor from Pawn and have that constructor operate on the Pawn instance:
function Pawn(/* args... */) {
Piece.call(this, color, type, captured, hasMoved);
/* Pawn-specific constructor code... */
}
I believe it's just a matter of setting the prototype of the specific piece constructors to an instance of Piece. For example:
Pawn.prototype = new Piece("", false, false);
However, this will not call the Piece (super) constructor every time you instantiate a new Pawn, so you'll have to manually assign color, type, etc. from the Pawn constructor:
-- EDIT --
You might prefer this instead: Javascript inheritance: call super-constructor or use prototype chain?
Take a look at this: https://github.com/haroldiedema/joii
var BaseClass = function()
{
this.some_var = "foobar";
/**
* #return string
*/
this.someMethod = function() {
return this.some_var;
}
};
var MyClass = new Class({ extends: BaseClass }, function()
{
/**
* #param string value
*/
this.__construct = function(value)
{
this.some_var = value;
}
})
Usage:
var obj = new MyClass("Hello World!");
console.log( obj.someMethod() ); // Hello World!

JavaScript OOP classes and declarations

Im finding it really difficult to grasp OOP in javascript.
Normally I would expect to have to create a class, and then create objects from that class.
However, according to one tutorial the following makes an object.
var egg = {}
Have I not just made an object named egg without actually making a class.
If thats the case how would I make multiple objects from an object :S
Also according to a different tutorial an object is made like below, which is completely difference to what I was told above :S
var Block = function(){
}
Can anyone help me unravel my confusion :(
Both of the above examples are correct. to put it simply EVERYTHING in javascript is an object. classes do not exist but there are many ways to imitate them. my favorite method is as follows:
var myClass = function() { <----------------------------- class declaration
var prop1,
prop2, <------------------------------------ private properties
prop3;
var addMe = function( arg1, arg2 ) { <------------ private method
var result = arg1 + arg2;
return result;
}
var obj = { <------------------------------------- constructor method
Prop1: prop1,
Prop2: value2, <----------------------------- public properties
Prop3: value3,
Method: function() { <------------------------ public method
obj.prop3 = obj.prop1 + obj.prop2;
return obj.prop3;
}
}
obj.Prop4 = addme( prop1, prop2 ); <-------------- public property set
with the private method
return obj;
}
var myClassObj = new myClass;
myClassObj is now an object of myClass with four public properties
Prop1, Prop2, Prop3, Prop4 and one public method called Method
Javascript is a different language than those that you have learned so far. You can't expect things to work exactly as they do when you change languages.
A quick sneak peek: in javascript, you can assign a function to a variable. I bet on those other languages you have used, that was not possible:
var myCounter = 1;
var myFunction = function(x){ return x + 1; };
Going back to your question: In javascript there are no "real classes". There are just objects. I know this might sound confusing at first.
Javascript's object model is called "prototypal inheritance". It's different than "classical" (pun intended) inheritance. And it is also not very cleanly implemented.
Basically, you start with one reduced set of objects (Array, Function, Object, etc. are Objects, not classes) and then you use those objects to build others. The relationships between them can be "class-and-instance-like", but they don't have to. They can be other kinds of relationships, too.
Since there are no classes, you can't create them. But you can create a regular object, assign it to the variable Car, and just think "I'm going to use this object to create lots of other objects. And those other objects will have some attributes by default, like methods and stuff, so that they behave like cars". And the language allows you do do that. Car will behave like a class does in other languages, and the objects it produces will be "like instances of Car".
To javascript, though, they will look like objects with some relationships between them.
In a way, prototypal inheritance is a "superset" of classical inheritance. You can do classical inheritance, but also other things.
Have I not just made an object named egg without actually making a
class.
That's right. All you're doing there is instantiating the base Object object - you've not made anything that you can make instances of.
In JavaScript there is no formalised concept of classes - there is merely a simulation of them, achieved by instantiating rather than invoking functions.
function Animal() { this.animal = true; }
Animal.prototype.sayHi = function() { alert(this.name+' says hi!'); }
function Dog(name) { this.name = name; }
Dog.prototype = new Animal();
...
var fido = new Dog('Fido');
fido.sayHi(); //"Fido says hi!";
Note the 4th line is just one of several means of simulating inheritance.
So in JavaScript, classes and functions are both just functions. There is nothing inherent to prevent a function intended for instantiation from being called without the new operator, nor visa-versa.
In the former case, the common workaround is to check that the constructor is the 'class' (if invoked and not instantiated, the constructor will be Object) and re-route as necessary:
function Dog(name) {
//if we weren't instantiated, the constructor will be Object, not Dog
if(this.constructor != Dog) return new Dog(name);
this.name = name;
}
var fido = Dog(); //bad - invocation should be instantiation
Yes var egg = {} is an object, but its not an instance of an object.
In javascript, simply saying something in that way is basically js's idea of a singleton, meaning it is exactly what it equals.
//this is a js singleton, and all properties of this object are public.
var egg = {
name: 'humpty',
smush: function() { console.log('splat!'); },
weight: '4oz'
};
console.log(egg.weight); //4oz
whereas, the more traditional type of object would be making it a function that you can then instantiate:
var Egg = function( name, weight ) {
var name = name;
this.smush = function() { console.log('splat!'); }
this.weight = weight;
};
var e2 = new Egg('dumpty','6oz');
console.log(e2.name); //will not return name. (since i wrote var name and not this.name, its "private" and thus cannot be accessed.)
console.log(e2.weight); //4oz
You want to look at "Prototypal Inheritance" for JavaScript.
http://www.crockford.com/javascript/inheritance.html
Create an object oriented with jQuery. Make use of the constructor() method and access public and private methods from within the class scope.
/*
* myClass
*/
var myClass = function(options){
/*
* Variables accessible
* in the class
*/
var vars = {
myVar : ''
};
/*
* Can access this.method
* inside other methods using
* root.method()
*/
var root = this;
/*
* Constructor
*/
this.construct = function(options){
$.extend(vars , options);
};
/*
* Public method
* Can be called outside class
*/
this.myPublicMethod = function(){
console.log(vars.myVar);
myPrivateMethod();
};
/*
* Private method
* Can only be called inside class
*/
var myPrivateMethod = function() {
console.log('private method called');
};
/*
* Pass options when class instantiated
*/
this.construct(options);
};
/*
* USAGE
*/
/*
* Set variable myVar to new value
*/
var newMyClass = new myClass({ myVar : 'new Value' });
/*
* Call myMethod inside myClass
*/
newMyClass.myPublicMethod();

Categories