Proper way of defining a javascript variable? - javascript

Is the below JavaScript code have the proper variable declaration, or any other way to define that ? may i know this method of variable declarations ?
var JQFUNCS = {
runFunc: {
"jsonp": {
run: function (id) {
var demobox = $('#' + id);
demobox.html('<img id="loading" src="images/loading.gif" />');
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?", {
tags: "jquery",
tagmode: "any",
format: "json"
}, function (data) {
demobox.empty();
$.each(data.items, function (i, item) {
demobox.append('<a href="' + item.link + '" target="_blank"><img style="max-width:150px;" src="' + item.media.m + '" alt="' + item.title + '" title="' + item.title + '" />');
if (i == 10) return false;
});
$('#' + id + ' #loading').hide();
});
},
reset: function (id) {
$('#' + id).empty().hide();
}
}
}
}

This method of variable declaration is called an Object Literal.
var objectLiteral = {
propertyOne: 1,
functionTwo: function() {
return 2;
}
};
Uses: Great for encapsulating data and functionality that belong together in a more traditional way. Protects from cluttering the global namespace from duplicated variable names. Only provides one instance of the object unless you use object copying tatics though.
You can also use a function declaration:
function funcDeclaration() {
this.propertyOne = 1;
this.functionTwo = function() {
return 2;
}
}
var obj = new funcDeclaration();
Uses: Allows for instantiation of objects, very much like classes. Has all the flexibility of a object literal plus some.
There isn't a right or wrong answer here. Some of it is situation, convention, or preference.
Heck you can even combine the two and get really tricky by employing a self executing function (if you are trying to emulate visibility modifiers):
var objectLiteral = (function() {
//currently within a self-executing function, syntax allows this
var privatePropertyOne = 1;
function privateFunctionTwo() { //yes, functions can contain other functions
return 2;
}
//the self-executing function returns and object literal that contains references to the privately scoped items defined above.
return {
PropertyOne: function() { return privatePropertyOne; },
FunctionTwo: privateFunctionTwo
};
})();
Uses: Pro and fun. =P Not necessarily readable and certainly blows the mind of any newbie javascript developer.

Related

Calling function from object in array (JS)

I have issues calling function "Izpis" from an array. Class below:
function Kandidat(ime, priimek, stranka, stDelegatov) {
if (ime == "" || priimek == "") {
alert("Podatki niso popolni!");
return;
} else {
this.ime = ime;
this.priimek = priimek;
this.stranka = stranka;
this.id = polje.length + 1;
this.stDelegatov = stDelegatov;
}
Izpis = function() {
return "(" + this.id + ")" + this.ime + " " + this.priimek + " pripada stranki " + this.stranka + ".";
}
PosodobiIzpis = function(ime, priimek, stranka, stDelegatov) {
this.ime = ime;
this.priimek = priimek;
this.stranka = stranka;
this.stDelegatov = stDelegatov;
}
}
I tried it like this:
var a = [];
a = a.concat(Isci($("#iskalniNiz")));
for (var i = 0; i < a.length; i++) {
var temp = (Kandidat)(a[i]).Izpis();
$("br:eq(0)").after(temp + "\n");
}
and without (Kandidat) with no success. I am getting either "is undefined" or "is not a function" error.
It looks to me as if Kandidat is meant to be a constructor function. The way you've defined Izpis is a bit sketchy...
If you want to make Izpis a property of an instance you're creating (using the new keyword), you need to write this.Izpis.
If you don't prefix it with this., nor with var, it will do one of two things:
If there's a globally defined Izpis, it will overwrite this variable.
If there's no Izpis variable defined in the current context, it will create a new one inside the constructor function, which will not be accessible outside of this code block.
Another issue I see in your code, that might not initially show, is that you are using this inside the Izpis and PosodobiIzpis functions.
This will break once you call your functions other than kandidatInstance.Izpis(). E.g.: setTimeout(kandidatInstance.Izpis) will not work.
To fix this, do either:
function YourConstructor(id) {
// Method 1: store 'this' context in closure
var self = this;
this.yourMethod = function() {
return self.id;
};
// Method 2: explicitly bind 'this' context
this.yourMethod2 = function() {
return this.id;
}.bind(this);
};
// Method 3: use prototype
YourConstructor.prototype.yourMethod3 = function() {
return this.id;
};

How avoid getter/setter functions in the module pattern when passing arguments

For some time now, I've been structuring my JavaScript Code like this:
;(function() {
function Example(name, purpose) {
this.name = name;
this. purpose = purpose;
}
Example.prototype.getInfo = function() {
return 'The purpose of "' + this.name + '" is: ' + this.purpose;
}
Example.prototype.showInfo = function() {
alert(this.getInfo());
}
var ex = new Example('someModule', 'Showing some stuff.');
ex.showInfo();
})(undefined);
Fiddle
Now I've realized that this pattern is far from ideal as is has some problems:
It doesn't utilize closures/scope so simulate public & private
members.
It doesn't export something, meaning the module itself is not really encapsulated & namespaced.
(Disclaimer: I haven't used it in any bigger project, so I might be missing some important details that occur when working under real live conditions.)
To solve these issues, I started looking into JavaScript design patterns. One of patterns that immediately appealed to me is the module pattern.
I tried to rewrite the code above using the module pattern, but I can't get it quite right:
var Example = (function() {
function getInfo() {
return 'The purpose of "' + name + '" is: ';
}
// Public stuff
return {
name: '',
purpose: '',
setInfo: function(name, purpose) {
this.name = name;
this.purpose = purpose;
},
showInfo: function() {
alert(getInfo());
}
};
})(undefined);
Example.setInfo('someModule', 'Showing some stuff.');
Example.showInfo();
Non working Example: Fiddle
Now the module itself is encapsulated inside the Example namespace & there is something like public & private members, but working with it is quite different & difficult to me, probably because I can't wrap my head around the fact that there is no instance created using the new keyword.
In the non working example, why does it alert result although that string is never set & why is purpose not alerted? I think the setInfo method itself works, so it's probably a scope issue I don't understand.
Also, is there a way around using getter/setter functions? To me it currently looks like assignments I would normally do in the constructor aren't really possible using the module pattern:
function Example(name, purpose) {
this.name = name;
this. purpose = purpose;
}
Using the module pattern, I either have to user getter/setter or something like a 'universal setter function' in form of an init function.
Coming from PHP OOP, I always try to avoid them as much as possible, but I don't really know how to handle that in a prototype based language.
Maybe there is something similar to the module pattern, but with using prototypes – something like module & constructor pattern? It might be easier for me to understand.
Use it this way and it should work and you are right, this is scope issue.
Here is the working fiddle
Notice that I have taken snapshot of this in a variable and am using that. It is usually done in order to keep a reference to this when the context is changing.
No use of new Keyword
In your case returning {} is returning a new instance of anonymous object with properties as defined. Hence, you do not need new keyword also. You can take a look at this for anonymous objects.
When you use this, the scope of this changes in return {} object and they no more refer to the Example object.
Using getter / setter function
You don't need them. assignments would do, but remember, the variables would be attached with self so you would need to do self.name = name and self.purpose = purpose in order to do assignments or get values.
var Example = (function() {
var self = this;
function getInfo() {
return 'The purpose of "' + name + '" is: ' + purpose;
}
// Public stuff
return {
name: '',
purpose: '',
setInfo: function(name, purpose) {
self.name = name;
self.purpose = purpose;
},
showInfo: function() {
alert(getInfo());
}
};
})(undefined);
Example.setInfo('someModule', 'Showing some stuff.');
Example.showInfo();
Update:
Fiddle wasn't saved properly I have updated that. Also In there I just corrected your code.
I think this is what you are trying to achieve:
var Example = (function (params) {
var self = this;
self.name = params.name;
self.purpose = params.purpose;
function getInfo() {
return 'The purpose of "' + self.name + '" is: ' + self.purpose;
};
self.showInfo(alert(getInfo()));
return{
};
});
var myExample = new Example({
name: 'someModule',
purpose: 'somePurpose'
});
myExample.showInfo();
I'm not sure if that's what you're trying to achieve:
http://jsfiddle.net/Ly66mcxo/1/
Example = (function() {
var _name, _purpose;
function getInfo() {
return 'The purpose of "' + _name + '" is: ' + _purpose;
}
// Public stuff
return {
setInfo: function(name, purpose) {
_name = name;
_purpose = purpose;
},
showInfo: function() {
alert(getInfo());
}
};
})(undefined);
Example.setInfo('someModule', 'Showing some stuff.');
Example.showInfo();
Check now
var Example = (function () {
var _this = this;
_this.getInfo = function () {
return 'The purpose of "' + _this.name + '" is: ' + _this.purpose;
}
return {
setInfo: function (name, purpose) {
_this.name = name;
_this.purpose = purpose;
},
showInfo: function () {
alert(_this.getInfo());
}
};
})(undefined);
Example.setInfo('someModule', 'Showing some stuff.');
Example.showInfo();

Can you dynamically add local variables to a function?

I'm using objects to namespace my JavaScript code. These objects usually contain functions that are called mapping the this-pointer to the object itself using apply. However, I find it inconvenient to use the this-pointer everytime I want to access other functions or properties of the object, especially because in lots of cases I use the new-operator to use function-objects the way you would use classes. I would prefer writing new Line() instead if new this.Line().
It would be great if you could add local variables to a function the way php does it with extract (pseudocode following, it's a little more complicated)
var sample_object = {
"some_function": function() {}
}
test() {
extract(sample_object);
some_function(); // imported from sample_object
}
Is that even possible?
I'm pretty sure eval is your only answer; but you need to be aware that if there's any input outside of your control involved, it isn't safe
function dynamicArgs (varName, varValue) {
eval("var " + varName + "=" + JSON.encode(varValue) );
alert(a);
}
dynamicArgs("a", "value");
You can see the problem with this. How is your function supposed to call the dynamic variable if it doesn't know its name? I hardcoded it to the a variable since I pass it in when calling it, but that's not a good solution. The only solution would be another eval. You really should think about what you need to do and whether this is useful. But it's doable.
Here it is in action: http://jsfiddle.net/mendesjuan/GG3Wu/
function dynamicArgs (varName, varValue) {
eval('var ' + varName + "='" + varValue + "';");
alert(eval(varName));
}
dynamicArgs("f", "Here I am");
Now here's an example like what you're doing, creating a variable from this.MyConstructor
http://jsfiddle.net/mendesjuan/AK3WD/
var ns = {
MyConstructor: function(val) {
this.prop = val;
},
runConstructor: function(val) {
var Ctor = "MyConstructor";
eval('var ' + Ctor + ' = this.' + Ctor);
return new MyConstructor(val);
}
}
alert( ns.runConstructor("Hello").prop );
And here's an example if you wanted to import all the values from an object into the scope;
http://jsfiddle.net/mendesjuan/AK3WD/1/
var ns = {
MyConstructor: function(val) {
this.val= val;
},
anotherProperty: 5,
runConstructor: function(val) {
// Bring all the variables from this into this scope
for (var prop in this) {
eval('var ' + prop + ' = this.' + prop);
}
alert('Testing var anotherProperty: ' + anotherProperty);
var obj = new MyConstructor(val);
alert('Created MyConstructor: its prop is ' + obj.val)
}
}
ns.runConstructor("Hello");
There is controversial with, which has some great applications, but is marginally slow and prone to errors. It throws an error in the strict mode (which you should always opt into) and is going to be deprecated.
var sampleObject = {
someFunction: function() {},
b: 10
}
with (sampleObject) {
typeof someFunction // "function"
var a = 42
var b = 20
}
sampleObject.a // undefined
sampleObject.b // 20
Note, that new variables defined in a with-block won't be added to the object. Nevertheless, if the object already had an eponymous property in it, this property would be modified (thanks, #Rocket).
Just for fun, here's an implementation of extract using eval (which is even more evil than with). You can do unspeakable things with it, for example if your object has properties like sampleObject['x; while (true) { alert("Hi!") }'].
This is how I did it:
function smObject ( object) {
return function () {
function getter(prop) {
return function() {
return this[prop];
}
}
function setter(prop) {
return function(data) {
this[prop]=data;
}
}
for (var o = 0; o < object.length; o++) {
this[object[o]] = {};
this['get' + object[o]] = getter(object[o]);
this['set' + object[o]] = setter(object[o]);
}
}
}
now you can instantiate a function like this:
var fields = ['Name', 'Id', 'Other', '....' ]
var MyFunction = smObject( fields );
var myObject = new MyFunction();
// getter/setters
myObject.setId(5);
myObject.getId(); // will return 5
Regards,
Emanouil

Method chaining in javascript

This working code is using Sproutcore:
person = SC.Object.create({
firstName: 'Foo',
lastName: 'Bar',
fullName: function() {
return this.get('firstName') + " " + this.get('lastName');
}.property()
});
console.log(person.get('fullName')); // "Foo Bar"
I wonder where property() is declared and how they have made this to work.
When I try to reconstruct this without the SC class, it gives me:
TypeError: Object function () {
return this.get('firstName') + " " + this.get('lastName');
} has no method 'property'
How does the code looks like to make it work?
Sproutcore is extending the function prototype.
Function.prototype.property = function() { /* code here */ };
The specific code use by sproutcore is at https://github.com/sproutcore/sproutcore/blob/master/frameworks/runtime/core.js#L908
SC.mixin(Function.prototype,
//...snip...
property: function() {
this.dependentKeys = SC.$A(arguments) ;
var guid = SC.guidFor(this) ;
this.cacheKey = "__cache__" + guid ;
this.lastSetValueKey = "__lastValue__" + guid ;
this.isProperty = YES ;
return this ;
},
//snip
);
In their case, they are using their own mixin method, but the concept is the same: extending the prototype
Presumably, Sproutcode has modified Function.prototype to include a property function.
You could just look at the source code.

Calling a function by a string in JavaScript and staying in scope

I've been playing around and searching a bit, but I can't figure this out. I have a pseudo private function within a JavaScript object that needs to get called via eval (because the name of the function is built dynamically). However, the function is hidden from the global scope by a closure and I cannot figure out how to reference it using eval().
Ex:
var myObject = function(){
var privateFunctionNeedsToBeCalled = function() {
alert('gets here');
};
return {
publicFunction: function(firstPart, SecondPart) {
var functionCallString = firstPart + secondPart + '()';
eval(functionCallString);
}
}
}();
myObject.publicFunction('privateFunctionNeeds', 'ToBeCalled');
I know the example looks silly but I wanted to keep it simple. Any ideas?
The string passed to eval() is evaluated in that eval()'s scope, so you could do
return {
publicFunction: function(firstPart, SecondPart) {
var captured_privateFunctionNeedsToBeCalled = privateFunctionNeedsToBeCalled;
var functionCallString = 'captured_' + firstPart + secondPart + '()';
eval(functionCallString);
}
}
However, a better solution would be to avoid the use of eval() entirely:
var myObject = function(){
var functions = {};
functions['privateFunctionNeedsToBeCalled'] = function() {
alert('gets here');
};
return {
publicFunction: function(firstPart, secondPart) {
functions[firstPart+secondPart]();
}
}
}();
myObject.publicFunction('privateFunctionNeeds', 'ToBeCalled');

Categories

Resources