Is this Object Oriented JavaScript? - javascript

I am using the following JavaScript, which I believe is Object Oriented. Others disagree that this is Object Oriented.
window.onload = function () {
var myphotos;
var currentImage;
var totalImageCount;
function initSlideImages(){
myphotos = new Array (
"slide_image_1",
"slide_image_2",
"slide_image_3",
"slide_image_4",
"slide_image_5"
);
currentImage = 1;
totalImageCount = myphotos.length;
}
initSlideImages(); // Initialise slideshow
function nextPhoto(){
currentImage++;
if (currentImage > totalImageCount) {
currentImage = 1;
}
var theImage = document.getElementById("slide_image");
if (theImage != null){
theImage.src = "images/portfolio/" + theImage.id + "_" + currentImage + ".jpg";
}
}
function previousPhoto(){
currentImage--;
if (currentImage == 0){
currentImage = totalImageCount;
}
var theImage = document.getElementById("slide_image");
if (theImage != null){
theImage.src = "images/portfolio/" + theImage.id + "_" + currentImage + ".jpg";
}
}
var slide_prev = document.getElementById("slide-prev");
if (slide_prev != null){
slide_prev.onclick = function() {
previousPhoto();
}
}
var slide_next = document.getElementById("slide-next");
if (slide_next != null){
slide_next.onclick = function() {
nextPhoto();
}
}
}
Would you agree this is Object Oriented JavaScript? I believe it is. There is Constructor functions (eg. initSlideImages) and literal notation objects (eg. myphotos, currentImage). "slide_prev" and "slide_next" are methods as far as I am aware from my understanding of OO JS.
Am I right, or do I need to revisit Object Oriented JavaScript 101?

This is a traditional JavaScript, no way related to OOJS. OOJS creates new objects and member functions. An example of OOJS would be:
function Person() { }
var person1 = new Person();
var person2 = new Person();
Or something like this:
var myObject = {
};
And this is how you define the methods:
function myObject(){
this.iAm = 'an object';
this.whatAmI = function(){
alert('I am ' + this.iAm);
};
};
Or, the literal version is like this:
var myObject = {
iAm : 'an object',
whatAmI : function(){
alert('I am ' + this.iAm);
}
}
References
Introduction to Object-Oriented JavaScript - MDN
The Basics of Object-Oriented JavaScript

There is Constructor functions (eg. initSlideImages)
The function initSlideImages is not used as a constructor.
and literal notation objects (eg. myphotos, currentImage).
Those are not literals in the sense I think you mean. They're just plain old global variables. And even if they were, that doesn't have much to do with OOP in JavaScript.
"slide_prev" and "slide_next" are methods as far as I am aware from my understanding of OO JS.
Those are not methods.
Am I right, or do I need to revisit Object Oriented JavaScript 101?
You're pretty far from right. None of the terminology in your post is used accurately. Yes, you should start over at the beginning.

Your code looks more procedural than object oriented. Object oriented often implies encapsulation and inheritance. In object oriented JavaScript your code would typically look something like this:
// Constructor
function Slider(photos) {
this.photos = photos;
this._init();
}
// Methods
Slider.prototype._init = function() {
// grab selectors, add events, initialization logic
};
Slider.prototype.count = function() {
return this.photos.length;
};
Slider.prototype.next = function() {
//...
};
Slider.prototype.prev = function() {
//...
};
var photos = [
"slide_image_1",
"slide_image_2",
"slide_image_3",
"slide_image_4",
"slide_image_5"
];
var slider = new Slider(photos);
slider.next(); // go to next slide

This is not object oriented JS.
There is no object instantiation using 'new' operator. There are no properties defined for a 'class like' constructor function.
Refactored object oriented code is as below:
function SlideImages(){
this.myphotos = new Array (
"slide_image_1",
"slide_image_2",
"slide_image_3",
"slide_image_4",
"slide_image_5"
);
this.currentImage = 1;
this.totalImageCount = this.myphotos.length;
}
//Object creation
var slideImages = new SlideImages();
//accessing object properties
console.log(slideImages.currentImage) //output:1

Related

Make a javascript function inherit a prototype [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I make a callable JS object with an arbitrary prototype?
Let's say we have multiple individual functions that we can call individually in their own context; But they also inherit some other object's prototype. Like this:
//Here is the parent object:
var Human = function(){
this.isAlive = true;
};
Human.prototype.say = function(what){
alert(what + '!');
};
//These will inherit from it:
var ninja = function() {
alert("I'm a ninja!");
}
var samurai = function(){
alert("I'm a samurai!");
}
//Now, how can I make ninja and samurai behave like this:
ninja(); //I'm a ninja!
samurai(); //I'm a samurai!
ninja.say('Hello'); //Hello!
//And they should keep their inheritance. Like:
Human.prototype.die = function(){
this.isAlive = false;
}
ninja.die();
ninja.isAlive == false;
samurai.isAlive == true;
In other words, is there a way to have two objects that inherit another object's prototype, but are still callable as functions?
Note: I'm gonna use this in Adobe ExtendScript (aka Crippled Javascript), and it doesn't know much modern javascript. Like, Object.defineProperty doesn't work in it. So, is there a normal, standard way to do this?
Using apsillers's linked question, I was able to get it working with one adjustment: Human's properties and methods are defined as an object:
Try it out: http://jsfiddle.net/lbstr/JZP2S/
The key is the HumanMaker function. At a basic level, it takes a function and adds the Human prototype to it. This allows you to invoke your function, get all of the properties from Human and eat it too. Here it is:
function HumanMaker(f) {
var h = Human;
h.__proto__ = f.__proto__;
f.__proto__ = h;
return f;
}
You would invoke it like this:
var ninja = HumanMaker(function() {
alert("I'm a ninja!");
});
Here is the whole thing:
var Human = {
isAlive: true,
say: function(what){
alert(what + '!');
},
die: function(){
this.isAlive = false;
}
};
function HumanMaker(f) {
var h = Human;
h.__proto__ = f.__proto__;
f.__proto__ = h;
return f;
}
//These will inherit from it:
var ninja = HumanMaker(function() {
alert("I'm a ninja!");
});
var samurai = HumanMaker(function(){
alert("I'm a samurai!");
});
//Now, how can I make ninja and samurai behave like this:
ninja(); //I'm a ninja!
samurai(); //I'm a samurai!
ninja.say('Hello'); //Hello!
ninja.die();
ninja.isAlive == false;
samurai.isAlive == true;​
I have always found the functional inheritance pattern much more easier to understand:
var human = function(){
var me = {};
var _isAlive = true;
Object.defineProperty(me, "isAlive", {
get: function() { return _isAlive}
});
me.say=function(what){
if(_isAlive)
alert(what+'!');
else
throw new Error('I am dead!');
}
me.die=function(){
_isAlive = false;
}
return me;
};
var person = function(){
var me = human();
return me;
};
var ninja = function(){
var me = human();
me.say = function(what){
if(me.isAlive)
alert(what+', I am a ninja!');
else
throw new Error('I am dead!');
};
return me;
};
var myPerson = person();
myPerson.say('hi');
var myNinja = ninja();
myNinja.say('hello');
I have left a demo here: http://jsfiddle.net/vtortola/nbpPt/
Cheers.

How should I look at structuring my JavaScript?

I'm having a little trouble working out how my JavaScript should be structured, etc..
My OOP skills in languages such as PHP, ActionScript 3 and so on are what I'm assuming to be on-par, but JS is lacking this which has thrown me off quite a bit in my learning.
I have a vague understanding of the prototype feature which I used a little in AS2 - I believe this is the closest I'll be able to get. At the moment, I'm laying out my code similar to this:
var slideshow =
{
property: value,
/**
* This is a method
*/
myMethod: function()
{
// do method things
}
};
// ------
slideshow.property ++;
slideshow.myMethod();
This all works okay, but it's void my ability to do something like:
var myslideshow1 = new Slideshow();
var myslideshow2 = new Slideshow();
myslideshow1.property = 10;
myslideshow2.property = 16;
I'm not sure on how to go about creating two different instances of one "object" I've created (in this case, slideshow).
I can't find any resources that explain the prototype feature in a way that makes sense.
Any pointers would be supoib.
Any javascript function can act as a constructor for a class, so try this:
function SlideShow(params) {
return {
property: value,
myMethod: function() {
//do method things
};
};
};
var slideshow1 = new SlideShow(params);
slideshow1.property = 10;
//etc.
I would frown apon using prototype to add methods to a class as there could be performance issues
Here is a sample class structure you could use. JavaScript classes are not much different the functions.
function MyItem(){
this.d = '';
this.clear = function( ) {
this.d = '';
}
}
var myItem = new MyItem( )
myItem.d = "test";
alert(myItem.d);
myItem.clear();
alert(myItem.d)
Some good reading here
You should avoid using the new operator, everything is public. A better way to do what you want to do, and have private variables and functions is to do the following:
var slideshow = function () {
var self = {};
var private_param = "hello";
var private_func = function(say) {
alert(say);
};
var method = function() {
private_func(private_param);
};
var param = 500;
self.method = method;
self.param = param;
return self;
// return object, with the method func and param param publicly accessible
// private_param and private_func are not accessible to the outside
};
var presentation = slideshow(); // new slideshow, you could edit to pass in init params
presentation.method(); // hello

Dynamically creating a new javascript class from an existing object

Say I have the following code:
var album = new MyObject('album');
Assume that when the object is constructed, a bunch of properties relative to only albums are loaded via AJAX. Would it be possible to create an Album class so that at a later point, I may just do this:
var anotherAlbum = new Album();
The Album constructor would automatically set the properties that are unique to album objects, based on what was loaded when creating MyObject('album')
JavaScript is prototypal, not classical, so if you think in terms of classes, you're doing it wrong.
You don't have to use the new operator at all. You can create a new object using the object literal:
var myObject = {attr1: 'val1', attr2: 'val2'};
Then you can create a new instance of that object:
var mySecondObject = Object.create(myObject);
Now you can change the attributes of mySecondObject, and if it has methods you can overload them just as easily:
mySecondObject.attr1 = "Hello";
mySecondObject.attr2 = function() {
return "World!";
};
And then mySecondObject will of course have all the properties that you gave myObject at creation.
Be aware that this is a simple version, and that this leaves all attributes 'public'. If you need some privacy, it can be achieved by adding some functions to the mix. It's a bit more complicated though, so let me know if you're interested...
JavaScript "classes", just like any other object, can be dynamically created. So, yes, this can be done.
You would do something like this in the code handling the AJAX response (assuming that the AJAX response was providing the name of the new "class", and it's in a variable called newClassName):
window[newClassName] = function() {
// New class name constructor code
}
window[newClassName].prototype = {
someProperty: "someValue",
someMethod: function(a, b) {
},
someOtherMethod: function(x) {
}
}
This is actually the only for of inheritance that JavaScript has. JavaScript has prototypal inheritance (which can be used to recreate classical inheritance). That means that inheritance is from another object, not a class definition.
To create an object that has all the properties of another object is simple:
function Album() {
// do whatever initialization you need to here, all the properties of album
// are available on 'this'
// e.g.,
doSomething(this.albumName);
}
Album.prototype = album;
var anotherAlbum = new Album();
You can use Douglas Crockford's Functional Inheritance Pattern. Code from Javascript Good Parts book
var mammal = function (spec) {
var that = {};
that.get_name = function ( ) {
return spec.name;
};
that.says = function ( ) {
return spec.saying || '';
};
return that;
};
var myMammal = mammal({name: 'Herb'});
var cat = function (spec) {
spec.saying = spec.saying || 'meow';
var that = mammal(spec);
that.purr = function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
};
that.get_name = function ( ) {
return that.says( ) + ' ' + spec.name +
' ' + that.says( );
return that;
};
var myCat = cat({name: 'Henrietta'});
It uses functions to decorate existing javascript objects with new functions and properties. Like this you can add new functions and properties on the fly to your existing object
You can do this
var NewClass=function(){
this.id=null;
this.name=null;
this.show=function(){
alert(this.id+" "+this.name;
}
}
NewClass.prototype.clear=function(){
this.id=null;
this.name=null;
};
...
var ins1=new NewClass();
var ins2=new NewClass();

JavaScript constructors

I do not understand quite completely how to apply constructors on this object creation method:
var MyObject = {
...
};
I know that you can do:
var MyObject = new Object();
MyObject.prototype.constructor = function(props)
{
...
}
or...
function MyObject(prop1, prop2)
{
this.prop1 = prop1;
...
}
Can I do something like this?
var MyObject = {
MyObject: function(prop1, prop2)
{
...
}
}
No, you can't, that would simply create a (static) method on MyObject -- MyObject.MyObject. In JavaScript, a constructor is the class. Class methods and properties are created either inside the constructor using this. or by adding to the prototype (outside of the constructor) using MyClass.prototype.. You can think of "objects" in JavaScript as static classes.
Example from here
Creating constructors
To write your own constructors, you use the this keyword within the constructor to refer to the newly-created object. The constructor initializes the object.
In the example below:
The make7Table constructor creates a multiplication table for number 7
The size property is introduced to keep track of the number of elements
The value of each element is initialized
function make7Table(numElements)
{
this.size = numElements;
var cnt;
for(cnt = 0; cnt < numElements; cnt++)
{
this[cnt] = cnt*7;
}
}
// Use the constructor to create and initialize an array.
myArray = new make7Table(10);
document.write(myArray[5]);
document.write("This table has " + myArray.size + " elements");
To run the code, paste it into JavaScript Editor, and click the Execute button. myArray[5] retrieves the element with the value of 5*7 = 35.
var MyObject = new Object();
MyObject.prototype.constructor = function(props)
{
...
}
is the same as
var MyObject = {};
MyObject.prototype.constructor = function(props)
{
...
}

Is there a difference between using "this" and "prototype" in Javascript here?

Is there a difference between the two codes below, I presume not.
function Agent(bIsSecret)
{
if(bIsSecret)
this.isSecret=true;
this.isActive = true;
this.isMale = false;
}
and
function Agent(bIsSecret)
{
if(bIsSecret)
this.isSecret=true;
}
Agent.prototype.isActive = true;
Agent.prototype.isMale = true;
There is a difference at least if you are assigning a non-primitive object to this.somevar or prototype.somevar.
Try running this:
function Agent(bIsSecret)
{
if(bIsSecret)
this.isSecret=true;
this.isActive = true;
this.isMale = false;
this.myArray = new Array(1,2,3);
}
function Agent2(bIsSecret)
{
if(bIsSecret)
this.isSecret = true;
}
Agent2.prototype.isActive = true;
Agent2.prototype.isMale = true;
Agent2.prototype.myArray = new Array(1,2,3);
var agent_a = new Agent();
var agent_b = new Agent();
var agent2_a = new Agent2();
var agent2_b = new Agent2();
if (agent_a.myArray == agent_b.myArray)
alert('agent_a.myArray == agent_b.myArray');
else
alert('agent_a.myArray != agent_b.myArray');
if (agent2_a.myArray == agent2_b.myArray)
alert('agent2_a.myArray == agent2_b.myArray');
else
alert('agent2_a.myArray != agent2_b.myArray');
No. 'prototype' used for implementing inheritance in Javascript. Such as that:
/** obsolete syntax **/
var Person = Class.create();
Person.prototype = {
initialize: function(name) {
this.name = name;
},
say: function(message) {
return this.name + ': ' + message;
}
};
var guy = new Person('Miro');
guy.say('hi');
// -> "Miro: hi"
var Pirate = Class.create();
// inherit from Person class:
Pirate.prototype = Object.extend(new Person(), {
// redefine the speak method
say: function(message) {
return this.name + ': ' + message + ', yarr!';
}
});
var john = new Pirate('Long John');
john.say('ahoy matey');
// -> "Long John: ahoy matey, yarr!"
code source and additional info you can find here: http://www.prototypejs.org/learn/class-inheritance
Functionally, this is the same. The latter, however, emphasizes similarities between Agent objects. You can see in a glimpse that these members have that value, while in a more complicated constructor function, with lots of conditionals, it's harder.
It also allows the javascript runtime to choose how it handles Agent member initializations. (do some precompilation, ...)
Assuming that this function is to be used as a constructor, the first with set properties on the new instance and the second on the prototype. If they are independent of the instance the two snippets are equivalent, but if they aren't (as their name suggest), then they are not.

Categories