I'am decided to "go deeper" with javascript, and before ECMA6 to try to master ECMA5 skills, and now i am stuck with object creation and initialization, what version is better, more practical, better to read and so on.
Which one to stuck with and use as foundation. So what i am tried:
Version 1, and is most popular in guides found googling
;(function() {
var magic = magic || {};
magic.doStuff = function() {
alert('Magic');
};
window.magic = magic;
document.addEventListener('DOMContentLoaded', function() {
magic.doStuff();
}, false);
})();
Version 2, quite as same as version 1, just a little bit different syntax
(function () {
var magic = {
doStuff: function() {
alert('Magic');
}
};
document.addEventListener('DOMContentLoaded', function () {
magic.doStuff();
}, false);
})();
Version 3, this one is worst for me, difficult syntax, more space for mistakes, and i am not even sure is it writen correctly
(function () {
var magic = (function () {
magic.doStuff = function () {
alert('Wow!');
};
return magic;
});
document.addEventListener('DOMContentLoaded', function () {
(new magic()).doStuff();
}, false);
})();
Version 4, this one was shown to me by senior dev, not so popular in guides, or it's just i didn't noticed it, but after some explanation probably is my favourite.
(function() {
var magic = (function () {
function publicDoStuff() {
alert('Magic');
}
return {
doStuff: publicDoStuff
};
})();
document.addEventListener('DOMContentLoaded', function () {
magic.doStuff();
}, false);
})();
I like to keep it simple for simple objects
var magic = {
doStuff: function () {
alert('Wow!');
},
};
document.addEventListener('DOMContentLoaded', function () {
magic.doStuff();
}, false);
If you use many instances of an object, then its faster to use prototype
Magic = function() {
};
Magic.prototype.doStuff = function() {
alert('Wow!');
};
Related
Problem:
I have a piece of code that throws an error: this.isEmpty is not a function,
and I cannot figure out why. Following is the fragment (jsfiddle):
function addAlbumGrid(){
const MainGrid = new AlbumGrid ()
return MainGrid
}
function AlbumGrid() {
MainGrid.call(this)
}
var parentPrototype = Object.create(AlbumGrid.prototype)
parentPrototype.constructor = MainGrid
MainGrid.prototype = parentPrototype
AlbumGrid.prototype.addPhotoBox = function () {
MainGrid.prototype.add.call(this)
}
function MainGrid(){
}
MainGrid.prototype = {
isEmpty: function() {
{
return false
}
},
add:function() {
if(!this.isEmpty())
{
return false
}
}
}
var AlbumGrid=addAlbumGrid()
AlbumGrid.addPhotoBox()
Following is code that works (jsfiddle):
function animal() {
}
animal.prototype = {
canWalk: function () {
return true
},
move: function () {
if(this.canWalk()) {alert ('moving')}
}
}
function bird() {
animal.call(this)
}
var animalProto = Object.create(animal.prototype)
animalProto.constructor = bird
bird.prototype = animalProto
bird.prototype.fly = function () {
animal.prototype.move.call(this)
}
let fluffy = new bird ()
fluffy.fly()
Searching for help I landed at this page, can it be that I am somewhere loosing the context of this, and it is pointing to something I don't want?
In that case, would a solution using composition be an option (object.assign(..))?
Or can it be anything else?
I hope somebody can shed a light.
Thank you...
Ps edit: I have now updated the code, the first 3 comments reflected an older version of this post.
How can I implement sub functions in JavaScript
callMethod(); // Works
callMethod.doThisWay(); // Still works
Sure you can :-)
Just write
const callMethod = function () {
// ...
};
callMethod.doThisWay = function () {
// ...
};
and you're done :-)
This also works:
var callMethod = function() {
this.doThisWay = function () {
alert('doThisWay');
}
alert('callMethod');
return this;
};
var a = new callMethod();
a.doThisWay();
there is some other ways to do this also.
So I asked a question awhile ago here > Cons of MouseOver for webpages and ran into some issues with enabling/disabling events. According to the answer from the post, I was supposed to update my function as an object to call it out easily. However after a few hours of trial and error as well as online research, I still don't understand how the object works
So this is the function I want to put into an object,
$(function () {
$('#01 img:gt(0)').hide();
setInterval(function () {
$('#01 :first-child').fadeOut(1500)
.next('img').fadeIn(1500)
.end().appendTo('#01');
}, 3000);
});
And this was the code provided to initialize my object,
var Slideshow = (function () {
this.interval;
this.start = function () {
...
initialize
...
// catch the interval ID so you can stop it later on
this.interval = window.setInterval(this.next, 3000);
};
this.next = function () {
/*
* You cannot refer to the keyword this in this function
* since it gets executed outside the object's context.
*/
...
your logic
...
};
this.stop = function () {
window.clearInterval(this.interval);
};
})();
So how exactly should I implement my function into the object so that it works?
I would structure it like this:
function Slideshow(container) {
this.interval = undefined;
this.start = function () {
container.find("img").first().show();
container.find("img:gt(0)").hide();
this.interval = window.setInterval(this.next, 3000);
};
this.next = function () {
var first = container.find(":first-child");
first.fadeOut(1500, function () {
first.next("img").fadeIn(1500);
first.appendTo(container);
});
};
this.stop = function () {
window.clearInterval(this.interval);
};
}
$(function () {
var div = $("#div01");
var slides = new Slideshow(div);
div.hover(function() {
slides.stop();
}, function() {
slides.start();
});
slides.start();
});
DEMO: http://jsfiddle.net/STcvq/5/
latest version courtesy of #Bergi
What you should aim to do, looking at the recommended code, is to move the logic of your setInterval inside the Slideshow.next() function. That basically covers your fadeout, fadein logic.
So your function would look something like:
this.next = function() {
$('#01 :first-child').fadeOut(1500)
.next('img').fadeIn(1500)
.end().appendTo('#01');
};
in the simplest of worlds.
Ideally, you would want to instantiate your Slideshow by telling it which id it should use, by passing that in the constructor. That is, you should be able to call
new Slideshow('#01') as well as new Slideshow('#02') so that you can truly reuse it.
Then, your next function would change to look something like (assuming the id is stored in this.elementId):
this.next = function() {
$(this.elementId + ':first-child').fadeOut(1500)
.next('img').fadeIn(1500)
.end().appendTo('#01');
};
Hope this helps
change syntax to :
var Slideshow = (function () {
return {
interval:null,
start : function () {
// catch the interval ID so you can stop it later on
this.interval = window.setInterval(this.next, 3000);
},
next: function () {
},
stop : function () {
window.clearInterval(this.interval);
}
};
})();
as you are using jquery, a better ans is to create a little plugin:
http://learn.jquery.com/plugins/basic-plugin-creation/
I'm working with Node.JS and have two objects that I move between via callbacks. I came up with a solution to maintain scope references to the correct object. I'm trying to figure out if there's a better way to do this, or if this is good practice.
function Worker () {}
Worker.prototype.receiveJob = function(callback, bossReference) {
this.doJob(callback, bossReference);
};
Worker.prototype.doJob = function(callback, bossReference) {
callback.call(bossReference);
// callback(); // this will not work
};
function Boss () {
this.worker = new Worker();
}
Boss.prototype.delegateJob = function() {
this.worker.receiveJob(this.whenJobCompleted, this);
};
Boss.prototype.whenJobCompleted = function() {
this.sayGoodJob();
};
Boss.prototype.sayGoodJob = function() {
console.log('Good job');
};
var boss = new Boss();
boss.delegateJob();
use Function.prototype.bind()
function Worker () {}
Worker.prototype.receiveJob = function(callback) {
this.doJob(callback);
};
Worker.prototype.doJob = function(callback) {
callback()
};
function Boss () {
this.worker = new Worker();
}
Boss.prototype.delegateJob = function() {
this.worker.receiveJob(this.whenJobCompleted.bind(this));
};
Boss.prototype.whenJobCompleted = function() {
this.sayGoodJob();
};
Boss.prototype.sayGoodJob = function() {
console.log('Good job');
};
var boss = new Boss();
boss.delegateJob();
you won't need those silly bossReferences aftewards unless you need it in your function
I've confused myself nicely here. My scenario is as follows:
function DesignPad() {
function EditBar() {
...
this.removeHandler = function() {
**// how do I call Dragger.removeAsset**
}
}
function Dragger(){
...
this.removeAsset = function() {}
}
this.init = function() {
this.editBar = new EditBar();
this.dragger = new Dragger();
}
}
var dp = new DesignPad();
...
I can't seem to call Dragger.RemoveAsset. I understand the why, my question is how do I call it?
I'm trying to keep like-things separated (e.g. Dragger / EditBar) but I seem to get all sorts of mixed up in my event handlers. Any suggestions, good reading materials, etc. on this stuff?
I found Douglas Crockford's Javascript to be the best introduction to JavaScript. Especialy videos for Yahoo, like: The JavaScript Programming Language where you can learn how exactly are objects created and inherited in JS.
Solution to you problem is:
function DesignPad() {
var that = this;
function EditBar() {
this.removeHandler = function() {
print("RemoveHandler");
that.dragger.removeAsset();
}
}
function Dragger() {
this.removeAsset = function() {
print("RemoveAsset");
}
}
this.init = function() {
this.editBar = new EditBar();
this.dragger = new Dragger();
}
}
var dp = new DesignPad();
dp.init();
dp.editBar.removeHandler();
But as others noticed you could refactor some things :).
To me it just looks like you should refactor that code to make it simpler.
I think that your issue comes from the fact that a nested function is private, so you can't access it from outside.
Is an instance of Dragger a 'property' of your DesignPad object? If so, you could pass a reference to that object into your removeHandler() method.
Try this:
function DesignPad() {
function EditBar(s) {
super = s;
this.removeHandler = function() {
alert('call 1');
super.dragger.removeAsset();
}
}
function Dragger(s){
super = s;
this.removeAsset = function() {
alert('call 2');
}
}
this.init = function() {
this.editBar = new EditBar(this);
this.dragger = new Dragger(this);
}
}
var dp = new DesignPad();
dp.init()
dp.editBar.removeHandler();
alert('end');