JavaScript convention: How do you assign arguments to the parent scope - javascript

var problemtest = function () {
var parameters;
return function (parameters) {
parameters = parameters;
}
}
var mysolutiontest = function () {
var parameters;
return function (parametersIn) {
parameters = parametersIn;
}
}
This is more of a JavaScript convention question.
Usually I have code similar to that on top. A function take arguments and assigns it to parent scope. However, I cannot use it as in problemtest, as the parameters that are arguments hide the parameters from problemtest.
In OO Programming we can use this, but in JavaScript I cannot use this, so I usually implement a solution similar to mysolutiontest. However, I am not fully satisfied with this solution. Is there a better way of doing this?

If your functions need to share some properties, then assigning them to an object is an elegant and common pattern:
var object = {
property: ['item'],
methodOne: function() {
console.log(this.property);
},
methodTwo: function() {
console.log(this.property);
}
};
object.methodOne(); // ['item']
object.methodTwo(); // ['item']
For further information on how 'this' works within an object - http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/

I usually use _parameters as a convention. This stems from my Java past. This isn't isolated to your example or to Javascript. Any language that does not force you to qualify the variables of any enclosing scope would lead you to the same problem.
var mysolutiontest = function () {
var _parameters;
return function (parameters) {
_parameters = parameters;
}
}
I've also seen people use p_parameters to quality function argument names. This is not one of my favorites tho.
var mysolutiontest = function () {
var parameters;
return function (p_parameters) {
parameters = p_parameters;
}
}
My 2c.

Related

How to escape "this" problem in a javascript class?

get_O3(e)
{
e.preventDefault();
let station = document.getElementById(e.target.id);
let lon = station.getAttribute('lon');
let lat = station.getAttribute('lat');
let code_station = station.getAttribute('code');
this.get_previsions(lon, lat, "O3").bind(this).then((data) =>
{
console.log(data);
});
}
I have a "this" problem, when i call the function get_previsions i get the error :
Uncaught TypeError: this.get_previsions is not a function.
It might be because of the (e) parameter because when i do a console.log(this) it returns the target. I would like that this == my class.
Thanks for the help
At any given point you can check what the current this reference is pointing to by doing the 4 following rules:
New: Was the function called using new then the this points to the new instance.
Explicit Binding: Was the function called using Function#call, Function#apply or Function#bind
Implicit Binding: Was the function called by its owner? (i.e. owner.foo() or owner["bar"]())
Default Rule: If none of the other rules happen then this is set to the window object if the script is running in "use strict" mode otherwise undefined.
Event-listeners call a function using Explicit binding (callBack.call(target, ...)) so the this reference gets set to the target. To change the this reference you either need to wrap it and call it implicitly or use Function#bind.
Implicit call Example (+ closure):
var something = {
foo: function() {
var self = this;
addEventListener("click", function(e) {
self.bar(e);
});
},
bar: function() {
}
};
Explicit call Example (Function#bind):
var something = {
foo: function() {
addEventListener("click", this.bar.bind(this));
},
bar: function() {
}
};
I'm assuming you have a class defined similar to
class thing {
get_O3(e) { ... },
get_previsions() { ... }
}
There are a few options for you. First option, you can bind all functions to this in the constructor:
class thing {
constructor () {
this.get_03 = this.get03.bind(this);
this.get_previsions = this.get_previsions.bind(this);
}
get_O3(e) { ... },
get_previsions() { ... }
}
This can get awkward, especially if you have many functions. You can write a helper bindAll function, but a less awkward/verbose solution is to use a factory method instead, bypassing this altogether:
function makeThing {
const thing = {
get_O3(e) {
...
thing.get_previsions();
},
get_previsions() { ... }
};
return thing;
}
Eric Elliot on Medium has some good reading on the topic if you want to get more in depth.

Creating JS library with dynamic function calling

I'm creating a JS 'library' file, But I want to encapsulate it in it's entirety within an object, to avoid contaminating namespace of the pages that include the file
The twist to this is within a function inside the library I need to call others functions within library by name, eg using window[]
The code below is just a sample there would actually be several hundred functions that could be called by name. It's this that's caused by trouble as I can't get window[] to reference the function, what's the right way to go about this?
I have tried this, in host page:
<script src= "mylib.js"></script>
var oMyLib = new cMyLib(); //there will only ever be one 'instance' of this
In mylib.js everything is contained in one function:
function cMyLib() {
this.doStuff = function () {
someFunc(this); //call another function in the lib
}
// I tried it with prototypes also
// cMyLib.prototype.doStuff = function () {
// someFunc();
// }
function someFunc(that) {
var s='anotherFunc1'
var f = window[s]; //undefined!
f();
s='anotherFunc2'
f=window[s];
f();
}
function anotherFunc1() {}
function anotherFunc2() {}
}
The functions that you want to reference by name (or actually by number, according to your comments) should be part of that object, and not accessed via window, e.g.:
function cMyLib() {
// allow call without new
if (! (this instanceof cMyLib)) {
return new cMyLib();
}
// enforce singleton
if (this.constructor.singleton) {
return this.constructor.singleton;
} else {
Object.defineProperty(this.constructor, 'singleton', {
value: this
});
}
// instruction array (no need to expose via `this`)
var insn = [];
insn[0x4c] = function lda_immediate() { ... }
// instruction execution
this.step = function() {
var opcode = memory[pc++];
if (opcode in insn) {
// `.call` ensures `this` is set inside the instruction fn.
insn[opcode].call(this);
} else {
hcf();
}
}
}
Note the extra stuff at the top - convenience code to ensure that only one cMyLib can exist.
As long as a function is in parent scope you can just reference it directly, i.e.
function someFunc(that) {
anotherFunc1();
};
will simply work.
Another thing is that classical way to do this is to wrap everything in a self-calling anonymous function, i.e.
(function() {
function anotherFunc1() {};
function anotherFunc2() {};
this.cMyLib = function() { ... };
})();
But your approach is fine as well.
If you wish to call your functions by dynamic name, then you can store them in a top level object:
(function() {
var my_functions = {
anotherFunc1: function() {},
anotherFunc2: function() {}
};
this.cMyLib = function() {
var name = 'anotherFunc1';
my_functions[name]();
};
})();
It's like creating an isolated "global" scope.
Side note: Do not use eval. It is very unsafe and slow. It will backfire at you at some point.

javascript is it possible to use a string to call a object function

I have a generic function which can speak to multiple other functions in appropriate objects is it possible to use a string to call the appropriate function.
var string = "save";
var generic = (new function (string) {
string."alert()";
return this;
})
var save = (new function (string) {
this.alert = (function () {
alert("your document has been saved")
return this
})
return this
})
var notSaved = (new function (string) {
this.alert = (function () {
alert("your document has not been saved")
return this
})
return this
})
I am using it for a far more complex set up but here is an example. Is this possible?
Sure you can. Try something like this:
window[string].alert();
Looking at your code it's hard to tell what you're actually trying to achieve. Nonetheless, here are a few ideas that may be relevant.
First, let's make a couple of objects:
var rabbit = {
name: 'Peter',
hop: function () {
return this.name + ' hopped!'
},
jump: function () {
return this.name + ' jumped!'
}
}
var hairy_maclary = {
name: 'Hairy Maclary',
jump: function () {
return this.name + ' jumped over the fence!'
}
}
Now, you could define a function which invokes the hop method on whichever object is passed to it:
function hop(object) {
return object.hop()
}
hop(rabbit) // 'Peter hopped!'
I'm not sure why you'd do this rather than invoking hop directly, but perhaps you want to do extra stuff before or afterwards.
If you wanted to you could create a completely generic function which would invoke a given method on a given object:
function invokeMethod(object, method) {
object[method]()
}
invokeMethod(hairy_maclary, 'jump') // 'Hairy Maclary jumped over the fence!'
This is a really strange thing to want to do, though. Perhaps you could provide more of an idea of what you're actually trying to do, since your example code is rather odd.
You can enclose your functions within some object so you can access by passing name of the property using some variable (in this case named string), eg. like that:
var string = 'notSaved';
var funcs = {};
funcs.save = new function(){
this.alert = function(){
alert('called save.alert()');
};
return this;
};
funcs.notSaved = new function(){
this.alert = function(){
alert('called notSaved.alert()');
};
return this;
};
funcs[string].alert();
See working example on jsfiddle.
If your variables are global (they should not), they are also automatically enclosed within window object, so you can call them also like that: window[string].alert(). This will not work for non-global functions (in this case my solution seems to be the only one not using eval()).
eval("alert('test');");
You can call functions with eval. Even you can declare functions.
eval("function test(){ alert("test");}");
test();

JavaScript - object's functions referencing its fields

Here is a (very) simplified version of my code:
function Ctor() {
this.i = 0;
this.increment = function() { this.i++; },
this.decrement = function() { this.i--; },
this.display = function() { alert(this.i); }
};
The problem is, when the code is run, under some circumstances this now points to something else. I do more or less understand that this changes context from one function to another, but I though my increment function (and the others) would, by the magic of closures, "remember" what this is supposed to be.
I tried just eliminating this altogether, and simply referencing i in the functions. That failed also.
What should these functions look like?
You can not rely on what's in this in JavaScript. More on this topic.
I see you probably want to introduce private attributes like in OOP languages. John Resig described this issue very well.
function Field(val){
var value = val;
this.getValue = function(){
return value;
};
this.setValue = function(val){
value = val;
};
}
var field = new Field("test");
field.value
// => undefined
field.setValue("test2")
field.getValue()
// => "test2"
JavaScript works a lot differently than conventional languages like Java, C++ or PHP. But you can get used to it :)
In the instances where this changes, you can do this:
function() { obj.display(); }
Example:
var obj = new Ctor();
function foo(fn) {
fn();
}
foo(function() {
obj.display();
});
An alternative is to modify foo() to accept the context to execute the function with, like this:
function foo(fn, context) {
fn.call(context);
}

javascript organisation

I came across this Q/A on javascript code organisation.
var DED = (function() {
var private_var;
function private_method()
{
// do stuff here
}
return {
method_1 : function()
{
// do stuff here
},
method_2 : function()
{
// do stuff here
}
};
})();
Currently I do this,
var DED = new Object;
DED = {
sidebar : {
method_1 : function (data){
//some stuff
},
method_2 : function(data){
//do more
}
},
main : {
//.......
},
globalVariables : {
//...
}
}
What is the advantage of one over the other?
Warning: newbie here.
As indicated, that method uses closures to implement private functions and data. It's an alternative to the constructor method (below). E.g.
var DED = new (function()
{
var private_var;
function private_method()
{
// do stuff here
}
this.method_1 = function()
{
// do stuff here
};
this.method_2 = function()
{
// do stuff here
};
})();
With the DED method shown in your question, there is no constructor. Rather the function returns an object created from an object literal. The functions in that object have the private variable and method closed into them.
What you return from the anonymous self-calling function (function(){})() is the interface you publish for your "module" (DED).
DED.method_1() is public. private_method/private_var are not accessible from outside but everything inside of your self-calling function has access to them.
If you like this kind of access-control this is a good way to prevent other developer from accidentally messing with the internals of your module. In a lot of cases i'd just go for a naming convention like a leading underscore to indicate internals.
Javascript is very dynamic and if someone really wants to mess with code they have no write-access to they will be able to do so. Edit: This turns out to be a wrong assuption and not the case for private data in constructors or closures. Please, see: http://www.crockford.com/javascript/private.html

Categories

Resources