jQuery function not returning - javascript

(function($){
$.a.b = {
title: "ABC",
init: function (id) {
/* do something here */
return id+'a';
}
};
})(jQuery);
When I try to call $.a.b.init('t'); it does not work, I mean it does not return as expected. Any suggestions?
The problem is not that $.a.b.init('t') is not working. Problem is that it returns the code of the whole function instead of returning say a string.
Thank you for your time.

try
$.a = [];
$.a.b = { ... }
or even better:
$.a = {b: {
title: "",
init: ...
}};
When using $.a.b a is undefined, so you cannot add to it.

Since $.a is not yet defined you cannot set the b property. First you'll need to create $.a. Alternatively, use a namespacing helper:
$.namespace = function(ns) {
var cur = $, split = ns.split('.');
while (split[0]) {
cur = cur[split.shift()] = {};
}
return cur;
};
$.namespace('a').b = { ... };
It can also be used with deeper namespaces:
$.namespace('a.b.c.d.e.f').g = 123;
$.a.b.c.d.e.f.g; // => 123

Related

Javascript: Internal array is not reset to outer objects

How do I grant access to inner properties of objects in the right way? This is what does break my application:
I have an object that handles an array (simplified here):
function ListManager() {
var list = [],
add = function (element) {
list.push(element);
},
clear = function () {
list = [];
};
return {
add: add,
clear: clear,
list : list
};
};
But I get this when using it:
var manager = new ListManager();
manager.add("something");
manager.clear();
console.log(manager.list.length); // <= outputs "1"!
Stepping through the code shows, that within the clear method, list becomes a new array. But from outside the ListManager the list ist not cleared.
What am I doing wrong?
This is because clear sets the value of var list, not the .list on the object returned from ListManager(). You can use this instead:
function ListManager() {
var list = [],
add = function (element) {
this.list.push(element);
},
clear = function () {
this.list = [];
};
return {
add: add,
clear: clear,
list : list
};
}
Using your current structure, you could do:
function ListManager() {
var list = [],
add = function (element) {
list.push(element);
},
clear = function () {
list = [];
};
getList=function(){
return list;
}
return {
add: add,
clear: clear,
list : list,
getList: getList
};
};
var manager = new ListManager();
manager.add("something");
console.log(manager.getList()); // ["something"]
manager.clear();
console.log(manager.getList()); // []
function ListManager() {
var list = [],
add = function (element) {
this.list.push(element);
},
clear = function () {
this.list = [];
};
return {
add: add,
clear: clear,
list : list
};
};
var manager = new ListManager();
manager.add("something");
manager.clear();
console.log(manager.list.length); // <= now outputs "0"!
As has already been explained, your issue is that when you do list = [], you are changing the local variable list, but you aren't changing this.list as they are two separate variables. They initially refer to the same array so if you modified the array rather than assigning a new one to just one of the variables, they would both see the change.
Personally, I think you're using the wrong design pattern for creating this object that just makes things more complicated and makes it more likely you will create problems like you did. That design pattern can be useful if you want to maintain private instance variables that are not accessible to the outside world, but it creates a more complicated definition and maintenance if everything is intended to be public.
One of my programming goals is to use the simplest, cleanest way of expressing the desired functionality.
So that end, since everything in this object is intended to be public and accessible from outside the object, this is a whole lot simpler and not subject to any of the types of problems you just had:
function ListManager() {
this.list = [];
this.add = function(element) {
this.list.push(element);
}
this.clear = function() {
this.list = [];
}
}
Or, perhaps even use the prototype:
function ListManager() {
this.list = [];
}
ListManager.prototype = {
add: function(element) {
this.list.push(element);
},
clear: function() {
this.list = [];
}
};

javascript closure: protecting inner variable

I'm using the revealing module pattern somewhat like this:
var SomeClosure = function () {
var SomeInnerVar = 4;
function InnerGetTheVar() {
return SomeInnerVar;
}
function InitClosure() {
// there's something else happening here that requires me to
// wait for document.ready before initializing the closure
setInterval(IncreaseSomeInnerVar, 10000);
}
function IncreaseSomeInnerVar() {
SomeInnerVar = SomeInnerVar + 1;
}
InitClosure();
return {
GetTheVar: InnerGetTheVar
}
}
$(document).ready(function () {
SomeClosure = SomeClosure();
});
Now why is it that if in the console I type this:
SomeClosure.GetTheVar = 2;
SomeClosure.GetTheVar; // outputs 2!
Why doesn't the closure keep SomeInnerVar protected? I don't want the outer scope to be able to change SomeInnerVar like that.
Thanks for your suggestions.
Actually, SomeInnerVar is still 'protected', in this sense. However, you are overwriting SomeClosure's GetTheVar attribute with the value 2, which isn't 'protected' in the same sense. In other words, you aren't modifying SomeInnerVar, you're modifying GetTheVar.
Instead of just returning an object literal, use Object.defineProperty:
var out = {};
if ( Object.defineProperty ) {
Object.defineProperty(out, 'GetTheVar', {
value: InnerGetTheVar,
writable: false
});
} else {
out.GetTheVar = InnerGetTheVar;
}
return out;

How can I call any function in a chain of functions, without the chaining?

Sorry if my question wasn't clear enough. I'll put my code here...
var chain = {
'fn_1' : {
//fn_1 code here
chain.fn_2();},
'fn_2' : {
//fn_2 code here
chain.fn_3();}
...and so on
}
Let's say if i wana call chain.fn_1(), is there a way I can do that without calling chain.fn_2()?
What I can think of right now is a flag, but that would be alot of excess flags probably for each function. Do you guys have any ideas?
If the series of functions each call the next one you're correct, you'd need to have some sort of flag. In all likelihood, what would be best would be to modify your functions so that they return the reference to the object. Then you could chain like so:
var chain = {
'fn_1': function () {
// do something here.
return this;
},
'fn_2': function () {
// do something here.
return this;
},
'fn_3': function () {
// do something here.
return this;
}
};
// call the full chain:
chain.fn_1().fn_2().fn_3();
// call only the middle.
chain.fn_2();
g.d.d.c's answer is best, but if you can't modify the object for some reason, you could do this:
var _oldFn2 = chain.fn_2
chain.fn_2 = function() { return; };
chain.fn_1();
chain.fn_2 = _oldFn2;
var chain = {
fn : ['fn1', 'fn2', 'fn3'],
call : function(name) {
var i = 0, pos = -1, l = this.fn.length;
for(i = 0; i < l; i += 1) {
if(this.fn[i] == name) {
pos = i;
}
if(pos !== -1) {
this[this.fn[i]]();
}
}
},
fn1 : function() {
alert('fn1');
},
fn2 : function() {
alert('fn2');
},
};
chain.call('fn1'); //chain
chain.fn1(); //single

Javascript Array of Functions

var array_of_functions = [
first_function('a string'),
second_function('a string'),
third_function('a string'),
forth_function('a string')
]
array_of_functions[0];
That does not work as intended because each function in the array is executed when the array is created.
What is the proper way of executing any function in the array by doing:
array_of_functions[0]; // or, array_of_functions[1] etc.
Thanks!
var array_of_functions = [
first_function,
second_function,
third_function,
forth_function
]
and then when you want to execute a given function in the array:
array_of_functions[0]('a string');
I think this is what the original poster meant to accomplish:
var array_of_functions = [
function() { first_function('a string') },
function() { second_function('a string') },
function() { third_function('a string') },
function() { fourth_function('a string') }
]
for (i = 0; i < array_of_functions.length; i++) {
array_of_functions[i]();
}
Hopefully this will help others (like me 20 minutes ago :-) looking for any hint about how to call JS functions in an array.
Without more detail of what you are trying to accomplish, we are kinda guessing. But you might be able to get away with using object notation to do something like this...
var myFuncs = {
firstFunc: function(string) {
// do something
},
secondFunc: function(string) {
// do something
},
thirdFunc: function(string) {
// do something
}
}
and to call one of them...
myFuncs.firstFunc('a string')
I would complement this thread by posting an easier way to execute various functions within an Array using the shift() Javascript method originally described here
var a = function(){ console.log("this is function: a") }
var b = function(){ console.log("this is function: b") }
var c = function(){ console.log("this is function: c") }
var foo = [a,b,c];
while (foo.length){
foo.shift().call();
}
Or just:
var myFuncs = {
firstFun: function(string) {
// do something
},
secondFunc: function(string) {
// do something
},
thirdFunc: function(string) {
// do something
}
}
It's basically the same as Darin Dimitrov's but it shows how you could use it do dynamically create and store functions and arguments.
I hope it's useful for you :)
var argsContainer = ['hello', 'you', 'there'];
var functionsContainer = [];
for (var i = 0; i < argsContainer.length; i++) {
var currentArg = argsContainer[i];
functionsContainer.push(function(currentArg){
console.log(currentArg);
});
};
for (var i = 0; i < functionsContainer.length; i++) {
functionsContainer[i](argsContainer[i]);
}
up above we saw some with iteration. Let's do the same thing using forEach:
var funcs = [function () {
console.log(1)
},
function () {
console.log(2)
}
];
funcs.forEach(function (func) {
func(); // outputs 1, then 2
});
//for (i = 0; i < funcs.length; i++) funcs[i]();
Ah man there are so many weird answers...
const execute = (fn) => fn()
const arrayOfFunctions = [fn1, fn2, fn3]
const results = arrayOfFunctions.map(execute)
or if you want to sequentially feed each functions result to the next:
compose(fn3, fn2, fn1)
compose is not supported by default, but there are libraries like ramda, lodash, or even redux which provide this tool
This is correct
var array_of_functions = {
"all": function(flag) {
console.log(1+flag);
},
"cic": function(flag) {
console.log(13+flag);
}
};
array_of_functions.all(27);
array_of_functions.cic(7);
If you're doing something like trying to dynamically pass callbacks you could pass a single object as an argument. This gives you much greater control over which functions you want to you execute with any parameter.
function func_one(arg) {
console.log(arg)
};
function func_two(arg) {
console.log(arg+' make this different')
};
var obj = {
callbacks: [func_one, func_two],
params: ["something", "something else"];
};
function doSomething(obj) {
var n = obj.counter
for (n; n < (obj.callbacks.length - obj.len); n++) {
obj.callbacks[n](obj.params[n]);
}
};
obj.counter = 0;
obj.len = 0;
doSomething(obj);
//something
//something else make this different
obj.counter = 1;
obj.len = 0;
doSomething(obj);
//something else make this different
Execution of many functions through an ES6 callback 🤗
const f = (funs) => {
funs().forEach((fun) => fun)
}
f(() => [
console.log(1),
console.log(2),
console.log(3)
])
Using ES6 syntax, if you need a "pipeline" like process where you pass the same object through a series of functions (in my case, a HTML abstract syntax tree), you can use for...of to call each pipe function in a given array:
const setMainElement = require("./set-main-element.js")
const cacheImages = require("./cache-images.js")
const removeElements = require("./remove-elements.js")
let htmlAst = {}
const pipeline = [
setMainElement,
cacheImages,
removeElements,
(htmlAst) => {
// Using a dynamic closure.
},
]
for (const pipe of pipeline) {
pipe(htmlAst)
}
A short way to run 'em all:
[first_function, ..., nth_function].forEach (function(f) {
f('a string');
});
the probleme of these array of function are not in the "array form" but in the way these functions are called... then...
try this.. with a simple eval()...
array_of_function = ["fx1()","fx2()","fx3()",.."fxN()"]
var zzz=[];
for (var i=0; i<array_of_function.length; i++)
{ var zzz += eval( array_of_function[i] ); }
it work's here, where nothing upper was doing the job at home...
hopes it will help
Using Function.prototype.bind()
var array_of_functions = [
first_function.bind(null,'a string'),
second_function.bind(null,'a string'),
third_function.bind(null,'a string'),
forth_function.bind(null,'a string')
]
I have many problems trying to solve this one... tried the obvious, but did not work. It just append an empty function somehow.
array_of_functions.push(function() { first_function('a string') });
I solved it by using an array of strings, and later with eval:
array_of_functions.push("first_function('a string')");
for (var Func of array_of_functions) {
eval(Func);
}
maybe something like this would do the trick:
[f1,f2,f3].map((f) => f('a string'))
Maybe it can helps to someone.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
window.manager = {
curHandler: 0,
handlers : []
};
manager.run = function (n) {
this.handlers[this.curHandler](n);
};
manager.changeHandler = function (n) {
if (n >= this.handlers.length || n < 0) {
throw new Error('n must be from 0 to ' + (this.handlers.length - 1), n);
}
this.curHandler = n;
};
var a = function (n) {
console.log("Handler a. Argument value is " + n);
};
var b = function (n) {
console.log("Handler b. Argument value is " + n);
};
var c = function foo(n) {
for (var i=0; i<n; i++) {
console.log(i);
}
};
manager.handlers.push(a);
manager.handlers.push(b);
manager.handlers.push(c);
</script>
</head>
<body>
<input type="button" onclick="window.manager.run(2)" value="Run handler with parameter 2">
<input type="button" onclick="window.manager.run(4)" value="Run handler with parameter 4">
<p>
<div>
<select name="featured" size="1" id="item1">
<option value="0">First handler</option>
<option value="1">Second handler</option>
<option value="2">Third handler</option>
</select>
<input type="button" onclick="manager.changeHandler(document.getElementById('item1').value);" value="Change handler">
</div>
</p>
</body>
</html>
This answered helped me but I got stuck trying to call each function in my array a few times. So for rookies, here is how to make an array of functions and call one or all of them, a couple different ways.
First we make the array.
let functionsArray = [functionOne, functionTwo, functionThree];
We can call a specific function in the array by using its index in the array (remember 0 is the first function in the array).
functionsArray[0]();
We have to put the parenthesis after because otherwise we are just referencing the function, not calling it.
If you wanted to call all the functions we could use a couple different ways.
For loop
for (let index = 0; index < functionsArray.length; index++) {
functionsArray[index]();
}
Don't forget the parenthesis to actually call the function.
ForEach
ForEach is nice because we don't have to worry about the index, we just get handed each element in the array which we can use. We use it like this (non arrow function example below):
functionsArray.forEach(element => {
element();
});
In a ForEach you can rename element in the above to be whatever you want. Renaming it, and not using arrow functions could look like this:
functionsArray.forEach(
function(funFunctionPassedIn) {
funFunctionPassedIn();
}
);
What about Map?
We shouldn't use Map in this case, since map builds a new array, and using map when we aren't using the returned array is an anti-pattern (bad practice).
We shouldn't be using map if we are not using the array it returns, and/or
we are not returning a value from the callback. Source
I know I am late to the party but here is my opinion
let new_array = [
(data)=>{console.log(data)},
(data)=>{console.log(data+1)},
(data)=>{console.log(data+2)}
]
new_array[0]
you got some top answers above. This is just another version of that.
var dictFun = {
FunOne: function(string) {
console.log("first function");
},
FuncTwo: function(string) {
console.log("second function");
},
FuncThree: function(string) {
console.log("third function");
}
}
/* PlanetGreeter */
class PlanetGreeter {
hello : { () : void; } [] = [];
planet_1 : string = "World";
planet_2 : string = "Mars";
planet_3 : string = "Venus";
planet_4 : string = "Uranus";
planet_5 : string = "Pluto";
constructor() {
this.hello.push( () => { this.greet(this.planet_1); } );
this.hello.push( () => { this.greet(this.planet_2); } );
this.hello.push( () => { this.greet(this.planet_3); } );
this.hello.push( () => { this.greet(this.planet_4); } );
this.hello.push( () => { this.greet(this.planet_5); } );
}
greet(a: string) : void { alert("Hello " + a); }
greetRandomPlanet() : void {
this.hello [ Math.floor( 5 * Math.random() ) ] ();
}
}
new PlanetGreeter().greetRandomPlanet();

extend properties in javascript

i have this code in javascript:
var object = {
get: function(id){
sel = document.getElementById(id);
sel.orig = {};
...
return object.extend(sel, object);
}
extend: function(el, opt){
for(var name in opt) el[name] = opt[name];
return el;
}
}
and in another js i have
var Multi = {
set: function(){
if(!this.orig["height"]) this.orig["height"] = this.offsetHeight;
...
return this;
}
}
object.extend(object,Multi);
and i call it like this:
object.get('myId').set();
but when in the "set" method, the property this.orig["height"] is always undefined, so it always will change the value and that's not the idea, i need to capture it the first time because im trying to make an Fx framework and i that's for the slideUp function, i need to keep the original height, so i can go back again.
Any ideas please? thank you
Now, in contrast to some people's answers comments being completely non constructive I assume your true question regards this little ditty:
extend: function(el, opt){
for(var name in opt) el[name] = opt[name];
return el;
}
and why it returns undefined? It does'nt... your problem lies elsewhere, because this works:
var object = {
get: function(id) {
el = document.getElementById(id);
el.orig = {};
return object.extend(el,object);
},
extend: function( el, opt ) {
for(var name in opt) el[name] = opt[name];
return el;
}
}
var Multi = {
set: function() {
if(!this.orig['height']) this.orig['height'] = this.offsetHeight;
console.log( this.orig['height'] ); // if the value of offsetHeight itself is not undefined, it is what is returned.
}
}
object.extend(object,Multi);
object.get('myId').set();
hey, thanks for the comments and overall for the answer Quickredfox!! i found the problem, in this part:
get: function(id) {
el = document.getElementById(id);
el.orig = {};
return object.extend(el,object);
},
i just changed to this:
get: function(id) {
el = document.getElementById(id);
if(!el.orig) el.orig = {};
return object.extend(el,object);
},
and voila!! thank you very much for your answer!

Categories

Resources