Which JavaScript would have better performance? - javascript

(function (window, $, undefined) {
"use strict";
var methods = {};
var thingOnPage = $('.class');
methods.init = function () {
};
methods.1 = function() {
};
methods.2= function() {
};
methods.3= function() {
};
if (thingOnPage.length > 0) {
methods.init();
}
}(window, jQuery));
This gets compiled and included on every page, but the init method will only be called if there is a specific class on the page.
My question is, would I be able to make this more efficient if the conditional statement wrapped the declaration of all the methods?
Thanks

Related

JSLint does not like .bind(this), but without it, this.obj cannot be accessed

I am optimizing my code for user with JSlint, i came to a small issue that i am trying to find a solution to. In the code below which works, JSlint complains about .bind(this). If i remove .bind(this), then the code does not know what is "this.selectorCache.get()" nor "this.someFunc()".
Is there a way to get this code working by removing .bind(this)?
/*jslint this:true, devel: true */
/*global jQuery, $, window, SelectorCache */
"use strict";
$(function () {
window.myApp = (function () {
var _this = this;
this.selectorCache = new SelectorCache();// selector cache function
this.someFunc = function () {
return 0;
};
this.selectorCache.get('#someID').click(function () {
if (_this.this.selectorCache.get('#someOtherID').val() === 1){
console.log(_this.someFunc());
}
}.bind(this));
}.bind(this));
}.bind(this));
Store the this context to another variable and use it in the callback.
I'd recommend you to use the bind(this) though and to find out why exactly JSLint complains.
window.myApp = (function () {
var _this = this;
this.selectorCache = new selectorCache();// selector cache function
this.someFunc = function () {
return 0;
}
this.selectorCache.get('#someID').click(function () {
if _this.selectorCache.get('#someOtherID').val() === 1{
console.log(_this.someFunc());
}
});
}
The solution #Erazhihel proposed should fix the problem. Another minimal way to fix it is by using ES6's arrow function instead.
/* global jQuery, $, window */
"use strict";
$(function() {
window.myApp = (function () {
this.selectorCache = new selectorCache();// selector cache function
this.someFunc = function (){
return 0;
}
this.selectorCache.get('#someID').click(() => {
if (this.selectorCache.get('#someOtherID').val() === 1){
console.log(this.someFunc());
}
};
});
});

JavaScript inheritance with Require.js and the Revealing Module Pattern

Question:
A seemingly simple question that I've been researching on and off the for past 2 weeks (please go easy as I'm new to all this!):
How does one neatly implement inheritance in JavaScript when using Require.js and the Revealing Module Pattern?
Example:
Here is an example module which is the base class of some type of 'Component':
define('Component', [], function () {
"use strict";
var _privateVar = 10;
var _doPrivateThings = function () { /* do stuff */ };
var init = function () { /* do stuff */ };
var update = function () { /* do stuff */ };
return {
init : init,
update : update
};
});
Next I want to implement CakeComponent which should inherit everything from Component and allow me to edit/add methods and properties:
define('CakeComponent', ['Component'], function (Component) {
"use strict";
// Setup inheritance
var CakeComponent = function() {}
CakeComponent.prototype = new Component();
// Add/edit methods/properties
CakeComponent.prototype.newMethod = function () { /* do stuff */ };
return {
init : CakeComponent.init,
update : CakeComponent.update,
newMethod : CakeComponent.newMethod
};
});
Firstly, I'm not sure if that makes complete sense, but secondly, my CakeComponent feels a bit gross because now I've got this CakeComponent redundancy everywhere and I've had to 're-reveal' the init and update methods.
I would really prefer something like this (I realise this doesn't make sense, it's really just pseudo-code):
define('CakeComponent', ['Component'], function (Component) {
"use strict";
this.extends(Component);
var newMethod = function () { /* do stuff */ };
return {
newMethod : newMethod
};
});
Any tips or suggestions would really be appreciated. Thanks.
Further Details
Maybe I should always be creating a class object within the define wrapper? I've seen people do this but it seemed unnecessary until I came across this problem.
Would the .call() method on the function object be useful at all in this context? e.g. using Component.call()
#Bergi please see below:
define([], function () {
"use strict";
var Component = function () {
var _privateVar = 10;
var _doPrivateThings = function () { /* do stuff */ };
this.init = function () { /* do stuff */ };
this.update = function () { /* do stuff */ };
};
return Component;
});
I have seen this model used before, called Universal Module Definition:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['Component'], factory);
} else {
root.CakeComponent = factory(root.Component);
}
}(this, function (Component) {
return {
newMethod: function(){ /* do stuff */ }
};
}));
You could try this, which is not "real" inheritance - in case it does not work - depending on environment, you might need to pass the base functions as well, which is a pity:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['Component'], factory);
} else {
root.CakeComponent = factory(root.Component);
}
}(this, function (Component) {
return {
init: Component.init,
update: Component.update,
newMethod: function(){ /* do stuff */ }
};
}));
You can read more to this Topic in this fantastic article about the Universal Module Definition

Simple JavaScript OOP Class

I'm using John Resig's simple OOP Class that is adapted to use "use strict" and taken from SO post.
In all examples I see the usage of Class.extend like so:
var MyObj = Class.extend({
init:function(){},
prop: "Property"
});
But I found a large disadvantage for me of using it in such way - I cannot have "private" variables, so I cannot store reference to this like var $this = this;.
I found the solution for my case, and now I using the Class.extend in following way:
var MyObj = Class.extend(new function(){
var $this = this;
this.init = function(){};
this.prop = "Property";
});
Everything works in my case, but I want to know if there some things that can cause me problems in a long run?
Does this way my application will consume much more memory in browser?
What alternative ways I have to implement my needs?
Note: I need to store $this, because I use heavily events and callbacks, so I want to refer "original" this easy to have access to all methods and properties on object.
EDIT: As requested, this is my code example:
(function () {
"use strict";
window.QuickPlay = Class.extend(new function () {
var $this = this;
this.init = function (initData) {
$this.elementsToHide.push(initData.el);
$(function () {
playProcessStart();
Sys.Application.add_load(function () {
$find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () { $this.setElementsVisibility(""); });
});
$this.setElementsVisibility("hidden");
});
};
this.elementsToHide = [];
this.setElementsVisibility = function (visibility) {
$.each($this.elementsToHide, function (i) {
$("#" + this).css("visibility", visibility);
});
};
});
} ());
You can use module pattern and maintain all the OOP. These kind of pattern gives your code more security and better organization.
//these are namespaces in javascript
window.project = window.project || {}; //this kind declarations prevents recreate the object
project.group = project.group || {};
//in the line below we can use $ instead jQuery, and use window and document instead ask for the browser every time.
(function (window, document, $) {
"use strict";
project.group.NameOfYourModule = function () {
var privateAttribute = true,
students = 32, //It's is a best practice declare everything in an unique var.
privateMethod = function () {
alert('Now I know OOP using jQuery');
};
return {
init: function () {
//this is a public method and we can initiate some private method;
privateMethod();
//we call a public method using this
this.publicMethod();
},
publicMethod: function () {
//this is a public method
}
};
};
$(function () {
var myclass = new project.group.NameOfYourModule(); //instantiate you class
myclass.init(); //initiate some public method
});
}(window, document, jQuery));
Working example at JsFiddle
How to work with Inheritance and Module Pattern here
I cannot have "private" variables
Of course you can. Either in the (currently unnecessary) (function () { … } ()); wrapper, or in your constructor (the init thing).
new function () {
Avoid that pattern! If you really need your code to work as it does now, use
(function () {
"use strict";
// Here's the place where you could put a private, static variable
// for example `var elementsToHide = [];`
var $this = {
init: function (initData) {
$this.elementsToHide.push(initData.el);
$(function () {
playProcessStart();
Sys.Application.add_load(function () {
$find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () {
$this.setElementsVisibility("");
});
});
$this.setElementsVisibility("hidden");
});
},
elementsToHide: [],
setElementsVisibility: function (visibility) {
$.each($this.elementsToHide, function (i) {
$("#" + this).css("visibility", visibility);
});
}
};
window.QuickPlay = Class.extend($this);
}());
I want to know if there are some things that can cause me problems
Yes. Multiple instances will hardly work, as they all do reference the same elementsToHide array. And you're not using any instance methods at (only a constructor and static elements on your class), so the class pattern seems quite unnecessary. Use a module instead. If you need single instances (and classes), the code should look like this:
"use strict";
window.QuickPlay = Class.extend({
init: function (initData) {
var $this = this;
this.elementsToHide = [];
$(function () {
playProcessStart();
$this.elementsToHide.push(document.getElementById(initData.el));
Sys.Application.add_load(function () {
$find("ctl00_ContentPlaceHolderMain_ctrlPlayPopup1").add_closed(function () {
$this.setElementsVisibility("");
});
});
$this.setElementsVisibility("hidden");
});
},
setElementsVisibility: function (visibility) {
$(this.elementsToHide).css("visibility", visibility);
}
});

Differences between function() and function($) in OO Javascript?

I like to create pretty OO javascript, sometimes with prototype and sometimes more native. In many cases I create javascript classes looking like this
var myObject = myObject || {};
myObject.Example1 = function () {
"use strict";
// ctor
function self() { }
// init
self.init = function () {
console.log("Example 1 did init");
};
return self;
};
myObject.Example2 = (function ($) {
"use strict";
// ctor
function self() { }
// init
self.init = function () {
console.log("Example 2 did init");
};
return self;
})($);
But I seem to have forgot why I can't create an instance of the function enclosed with () and $.
var obj1 = new myObject.Example1();
obj1.init(); // Does init
var obj2 = new myObject.Example2();
obj2.init(); // Does not init (obj2.init is not a function)
The myObject.Example1() works as expected but why can't I call the myObject.Example2()?
The correct way to use the pattern ‘make an object from a closure’ would be like this:
myObject.Example2 = (function ($) {
return function () {
"use strict";
// ctor
function self() { }
// init
self.init = function () {
console.log("Example 2 did init");
};
return self;
}
})($);
Example2 is the return value of a function that defines a function called self, adds a property to it, and then returns that function.
Example1 has an almost identical function, but since you don't have () at the end, it isn't called, so the value of Example1 is that function and not the function defined inside it.
This has nothing to do with the difference between function () { and function ($) { and everything to do with the difference between }; and })($).
The $ argument is entirely irrelevant since you don't use $ inside the function.

Invoke javascript function from string

I have the following code in my javascript module, however this requires me to make the functions visible to the outside world.
var mymodule = function() {
var self = null,
init = function () {
self = this;
$('.actionButton').click(function () {
var worklistId = $(this).data('worklistid'),
action = $(this).data('action');
self[action] && self[action](worklistId); //watchout methods marked as not used are used by this invocation
})
},
send = function () {
// some logic
},
finish = function () {
// some logic
},
delete = function () {
// some logic
};
return {
init: init,
send: send,
finish: finish,
delete: delete
};
}();
mymodule.init();
So the only thing I want to return in my module is the init function. However when I do this I cant invoke the functions, because the object (self) only contains the init function visible on the outside.
return {
init: init
};
Is there any solution to invoke my functions like this without making them visible to the outside world? Please no if else statements, because my workflow is bigger then the 3 actions in this example. I want to make my module as closed as possible because this reduces the dependencies.
Update
Here is a updated jsfiddle with one of the proposed solutions, however this is giving me another issue. http://jsfiddle.net/marcofranssen/bU2Ke/
Something like this would work:
var mymodule = function() {
var self = this;
init = function () {
$('.actionButton').click(function () {
var worklistId = $(this).data('worklistid'), action = $(this).data('action');
self[action] && self[action](worklistId); //watchout methods marked as not used are used by this invocation
})
}
self.send = function () {
console.log('send');
}
self.finish = function () {
console.log('finish');
}
self.delete = function (item) {
console.log('delete');
};
return {
init: init,
};
}();
mymodule.init();​
Here's the fiddle:
http://jsfiddle.net/yngvebn/SRqN3/
By setting the self-variable to this, outside the init-function, and attaching the send, finish and delete functions to self, you can use the self[action] syntax from within the init-function
Yes, there is an easy (but perhaps slightly messy) way you can do this without making the functions visible to the global object:
var privateFunctions = { deleter: deleter, send: send};
Then, instead of self[action]();, just do privateFunctions[action](); and you're good to go.
Note that I changed delete to deleter, because delete is a reserved keyword...
var mymodule = function() {
var self = {},
init = function () {
$('.actionButton').click(function () {
var worklistId = $(this).data('worklistid'),
action = $(this).data('action');
self[action] && self[action](worklistId); //watchout methods marked as not used are used by this invocation
})
};
self.send = function () {
// some logic
};
self.finish = function () {
// some logic
};
self.delete = function () {
// some logic
};
return{
init:init
}
}();
mymodule.init();
This should Work!!
Even if you return an object just with the init property and you populate the rest dynamically such that your module uses them, you would still be making them visible to the outside at runtime. Anyone who wants to debug your module would easily get to them.
You can still create anonymous methods at runtime and they would also be visible together with their implementation.
In your code example, it is vague what "self" really is. You should keep it simple, use encapsulated functions as "private" methods and return a "public" (or "privileged" as Crockford calls it) function that have access to them.
This is the YUI way of doing singletons with private functions and variables. Example pattern:
var mymodule = (function() {
var internal = {
'send': function() {},
'finish': function() {},
'delete': function() {}
};
return {
'init': function(action) {
// access to internals, f.ex:
if ( internal.hasOwnProperty(action) ) {
internal[action].call(this); // bring the caller context
}
}
};
}());
mymodule.init('send');

Categories

Resources