How to make the object as public without removing var in javascript - javascript

(function(){
var a = {};
a.b = function(){
alert('this is b');
}
}());
How to make the 'a' object as public in above code without removing 'var', means 'a' can access even from another file like below.
(function(){
a.b();
}());
Note: Dont say to remove 'var', i know that way. But i want to is their any other way that without removing 'var'.

You can attach it to the global scope. In web browsers, this is the window object.
window.a = {};
Later on, you can reference it by window.a or just a.
This is generally discouraged though as collisions can occur when two unassuming scripts run and define the same thing. It would be much better to wrap whatever you need in closures.

You can return a from the IIFE:
var a = (function(){
var a = {};
a.b = function(){
alert('this is b');
}
return a;
}());
or create a property to window:
(function(){
var a = {};
a.b = function(){
alert('this is b');
}
window.a = a;
}());

Related

Is there a JavaScript DEFINE directive equivalent?

Inside a php file I have a script such as this snippet:
<script>
$(function(){
$("#tabs_<?php echo $keyCode ?>").tabs();
var x = document.getElementById("bkhmode_<?php echo $keyCode ?>");
var mode = x.value;
setcont_<?php echo $keyCode ?>(mode);
});
</script>
I want to remove this piece of code along with many other lines like it into a separate JS file to take advantage of caching BUT I have been unable to find the equivalent of a DEFINE command to allow me to replace the php echo.
I would like to
DEFINE KEY_CODE = 'somevalue';
then the snippet would look something like this:
<script>
$(function(){
$("#tabs_KEY_CODE").tabs();
var x = document.getElementById("bkhmode_KEY_CODE");
var mode = x.value;
setcont_KEY_CODE(mode);
});
</script>
Most languages allow for this but I have been unable to find anything equivalent in JavaScript. Any suggestions?
You may set variables to the global window namespace, although it is considered bad practice as it can interfere with other programs, so be careful.
window.KEY_CODE = 'somevalue';
$(function() {
$("#tabs_" + window.KEY_CODE); // Will escape local scope.
});
That should work, although it's common practice to do this with an IIFE.
(function(window, document, $, undefined) {
$("#tabs_" + window.KEY_CODE); // Will escape local scope.
})(window, window.document, window.jQuery);
That helps resolve a lot of namespace issues because they're explicitly defined in the local scope.
You can also use global variables to run a function.
If your function is declared outside of an IIFE (i.e. you've just run it in a global namespace), it's appended to the window element as well. For instance, these are equivalents.
function foo(a)
{
console.log("foo" + a);
}
foo("bar"); // prints "foobar"
window.foo("bar2"); // prints "foobar2"
window['foo']("bar3"); // prints "foobar3"
This is because the browser will assume you're calling window.foo if the local variable foo is undefined. window['foo'] is an identical way of calling window.foo; it accesses the window object, but using a string. So, with that in mind, we can accomplish your variable function call.
window.KEY_CODE = 'somevalue';
window.func_somevalue = function(a) {
console.log("somevalue = " + a);
};
window.func_othervalue = function(a) {
console.log("othervalue = " + a);
}
// prints "somevalue = Hello."
window['func_' + window.KEY_CODE]("Hello.");
You can do this with other objects.
window.KEY_CODE = 'somevalue';
(function(window, document, $, undefined) {
$("#tabs_" + window.KEY_CODE); // Will escape local scope.
var keys = {
'somevalue' : function(a) { console.log(a); },
'othervalue' : function() { console.log('other'); }
};
keys[window.KEY_CODE]("Hello.");
})(window, window.document, window.jQuery);

Access Variable from a different function without creating global variables

I've recently started using CasperJS to do web automation, and something is confusing me a little.
How do access local variables from one function to another? For example:
casper.start('http://google.com', function(){
var someVar = 20;
});
casper.thenOpen('http://google.com/analytics', function(){
// How can I access someVar?jav
});
I know someVar is not in scope in the second function, but how do I access someVar in the second function without defining globals?
What about using an object to get a certain variable as property:
var myObj = {};
casper.start('http://google.com', function(){
myObj.someVar = 20;
});
casper.thenOpen('http://google.com/analytics', function(){
console.log(myObj.someVar);
});
Without using Globals you say, then create a third function (bean) which would have var someVar = 20; local variable and provide getter and setter functions to use by others.
var SharedSpace = (function(){
var shared = 20; //initialization
return {
getShared: function(){
return shared;
},
setShared: function(val){
shared = val;
}
}
})();
(function(){
alert(SharedSpace.getShared());
SharedSpace.setShared(500)
})();
(function(){
alert(SharedSpace.getShared());
SharedSpace.setShared(400)
})();
(function(){
alert(SharedSpace.getShared());
SharedSpace.setShared(10)
})();
You can't do this so that it is clean and makes sense. Defining a global variable is the only clean way. You could of course put the variable on the casper object, but that is not clean as it might interfere with the CasperJS functionality if you use wrong variable names. I only do this when I define helper functions for casper.
casper.start('http://google.com', function(){
this.someVar = 20;
});
casper.thenOpen('http://google.com/analytics', function(){
this.echo(this.someVar);
});

javascript: access all variables of a parent function

I decided to create a funcB function that I call from funcA. I want all variables from funcA to be available in the funcB so func B can change that variables.
How to modify the code below so it meets my requirements? I doubt passing all variables it the only possible and the best way.
function funcB(){
alert(var1);//how to make it alert 5
alert(var20);//how to make it alert 50
}
function funcA(){
var var1=5;
...
var var20=50;
funcB();
}
var obj = {
one : "A",
two : "B",
fnA : function() {
this.fnB(); // without fnB method result will be displayed as A B, with fnB as C D
console.log(this.one + " " + this.two);
},
fnB : function() {
this.one = "C";
this.two = "D";
}
};
obj.fnA();
this keyword refers to obj object
You can define object with properties and methods inside it. With methods all the variables can be manipulated as you wish, from this example with fnB I'm changing values of properties which are displayed from fnA method
JSFiddle
One way is to drop the var keyword:
function funcB(){
alert(var1);//how to make it alert 5
alert(var20);//how to make it alert 50
}
function funcA(){
var1 = 5;
var20 = 50;
funcB();
}
This will expose them to the global scope so funcB can access them. Notice you can also create the varaibles in the global scope itself, with the var keyword, but both methods will ultimately have the same effect.
Note:
This may not work if there is already a var1 or var20 in the global scope. In such case, it will modify the global value and may result in unwanted errors.
This method is not preferred for official code, and is bad practice Reason
This is not possible as when you declare a variable with the var keyword, they are scoped to the function in which they are declared.
If you avoid the var keyword, they are instead defined as a global variable. This is deemed very bad practice.
I would recommend you read up on javascript coding patterns, particularly the module pattern.
For example:
var myNamespace = (function () {
var foo, bar;
return {
func1: function() {
foo = "baz";
console.log(foo);
},
func2: function (input) {
foo = input;
console.log(foo);
}
};
})();
Usage:
myNamespace.func1();
// "baz"
myNamespace.func2("hello");
// "hello"

Access a function's property inside the function

I want to be able to assign a property to a function inside the function itself. I do not want to assign it to the object of invocation. So I want the equivalent of doing this:
var test = function() {
return true;
};
test.a = 'property on a function';
alert(test.a);
Instead of this, where the property is assigned to a global object:
var testAgain = function() {
this.a = "this property won't be assigned to the function";
return true;
};
testAgain();
alert(window.a);
Edit: To clarify, I'm wondering if there's something like this:
var test = function() {
function.a = 'property on a function';
};
alert(test.a); // returns 'property on a function'
Without knowing that the function is called test or having to execute it.
I know of course this isn't valid syntax
[is there a way to set a property on a function] without knowing that the function is called test or having to execute it.
Emphasis mine.
You can set a property on a function without knowing what its global variable name is necessarily going to be, however you do have to have a reference to the function in one way or another.
The module pattern is as close of a fit as I can think of:
window.test = (function () {
//the function could be named anything...
function testFn() {
...code here...
}
//...so long as the same name is used here
testFn.foo = 'bar';
return testFn;
}());
window.test.foo; //'bar'
The outer closure prevents testFn from being accessed anywhere globally, so all other references will have to use window.test.
This part of the answer is associated with the prior version of the question.
The simplest way of doing this is to use a named function:
var test = function testFn() {
testFn.foo = 'bar';
return true;
};
test.foo; //undefined
test();
test.foo; //'bar'
A better way of doing this is to use the module pattern so that you don't accidentally create issues with global leakage:
var test = (function () {
function ret() {
ret.foo = 'bar';
return true;
}
return ret;
}());
test.foo; //undefined
test();
test.foo; //'bar'
var testAgain = function() {
arguments.callee.a = "this property won't be assigned to the function";
return true;
};
testAgain();
alert(testAgain.a);​
You can do this by simple using the name to assign the property like this:
var test = function () {
test.a = 'a';
return true;
};
When test is invoked, the property will be set.
Demo
You could use arguments.callee, as su- said, but that's considered really bad practice. Also, it won't work in strict mode.
var test = function() {
test.a = 'a';
};
Or you can use prototypes, read more here.

How to cache/precalculate something(without global variable)?

What I want to do is to sending data between two handlers.
element.onmousedown = function() {
data = precalculate();
}
element.onmouseup = function() {
dosomething(data);
}
if the data is a global variable it works. People says global variable is evil. But I don't know how to do without it.
or I misunderstood "global variable"?
Just scope the variable if you don't want/need it to be global:
(function() {
var data;
element.onmousedown = function() {
data = precalculate();
}
element.onmouseup = function() {
dosomething(data);
}
})();
EDIT: To clarify, the only way to create a new variable scope in javascript is in a function.
Any variable declared with var inside a function is inaccessible to the outer scope.
In the code above, I created an IIFE (immediately invoked function expression), which is simply a function that is invoked as soon as it is created, and I placed your data variable (along with the handler assignments) inside of it.
Because the handlers were created in a scope that has access to the data variable, they retain their access to that variable.
To give another example:
var a = "a"; // global variable
(function() {
var b = "b"; // new variable in this scope
(function() {
var c = "c"; // new variable in this scope
// in this function, you have access to 'a', 'b' and 'c'
})();
// in this function you have access to 'a' and 'b' variables, but not 'c'
})();
// globally, you have access to the 'a' variable, but not 'b' or 'c'
In this case a global variable would make sense. Another possibility is to attach the value to the DOM element:
element.onmousedown = function() {
// 'this' should point to the element being mouse downed
this.data = precalculate();
};
element.onmouseup = function() {
// 'this' should point to the element being mouse upped
var data = this.data;
dosomething(data);
};
You misunderstood "global variable is evil".
In fact, what really happened is that someone wanted to be "part of the crowd", and so told you a sweeping generalisation, when in fact they should have said "only use global variables where appropriate".
Well, they are appropriate here, my friend.
JQuery makes this possible by using the .data() function:
http://api.jquery.com/jQuery.data/
You can get away with using global variables as long as you keep them to a minimum, for example you can place stuff in a single global namespace:
App = {};
element.onmousedown = function() {
App.data = "hello";
}
element.onmouseup = function() {
console.log(App.data);
}
Another more general solution is to create functions that cache their results using a technique that is called memoization. There's plenty of stuff if you search.
The following code does exactly that :
Function.prototype.memoize = function() {
var fn = this;
this.memory = {};
return function() {
var args = Array.prototype.slice.call(arguments);
return fn.memory[args] ? fn.memory[args] : fn.memory[args] = fn.apply(this, arguments);
};
};
e.g. You have an expensive function called exfunc..
newFunc = exfunc.memoize();
The above statement creates a new function called newFunc that caches the result of the original function so that the first time the actual code is being executed and all subsequent calls are retrieved from a local cache.
This mostly works with functions whose return value does not depend on global state.
More info :
http://osteele.com/archives/2006/04/javascript-memoization

Categories