In the case of accessing the function variable previously to the declared scope, I would suggest that you do this in the function property, as it would become difficult or impossible to access the previously declared variable.
Instead of doing like this:
function x() {
var a = 1;
function z() {
var a = 2;
}
}
It could be done like this:
function x() {
x.a = 1;
function z() {
z.a = 2;
console.log(x.a); // Imprime '1'
}
}
Generally, there are some special cases where it is necessary to access a variable with previous scope, to simulate something similar to static variables.
When there is this need, I usually use a self invoking Function, with its declared variables, being accessed by a function in the return.
Example:
var noMultihits = function ()
{
var timeout = 0;
return function (time, callback) {
// Sempre limpa o timeout anterior
// A variável é de outro escopo
clearTimeout(timeout);
timeout = setTimeout(callback, time)
}
})();
noMultihits(500, function (){});
noMultihits(500, function (){});
noMultihits(500, function (){});
// Só executa o último, pois a variável é do escopo da funçao autoexecutável
The advantage of that is:
Do not pollute the global scope.
If it does not pollute the overall scope, there is no risk of collision of variable names.
Still using the self invoking functions (self executable functions) it is possible to join the two solutions, to use something I would call an anonymous object.
var ajaxInfinito = (function anonimo()
{
anonimo.pagina = 1;
return function () {
console.log(anonimo.pagina);
$.ajax({
url: 'pagina',
data: {pagina: anonimo.pagina},
success: function () {
anonimo.pagina++
}
});
}
})()
ajaxInfinito(); // 1
ajaxInfinito(); // 2
ajaxInfinito(); // 3
ajaxInfinito(); // 4
ajaxInfinito(); // 5
console.log(anonimo); // undefined, só existe no escopo da self-invoking
In that case we shall make important observations:
ajaxInfinito
will only receive the value of the function that is in the return
of expression anonimo
.
anonimo
is not a statement of a function, but an expression. I would call it a named closure. Note that the console.log
anonymity will say that the variable does not exist. This is because that name is only valid within the scope of the autoexecutable function.
As we are in another scope, the value of anonimo.pagina
will always increase with each call, since it is part of the scope of the autoexecutable function whose internal name is anonimo
.
Where access to anonimo
, the function could be used with.
Behold:
var soma = (function obj(){
obj.y = 4;
obj.z = 5;
return function () {
var x = 3;
with(obj) {
x += y;
x += z;
}
return x;
}
})();
soma(); // 12
Change of context
@Guilhermelautert commented on the use of this
. It is not possible to use it directly, since the context of the functions when called is window
. Only when they are instantiated this
refers to the object itself.
What can be done is to change the context in which the this
is used by the function, passing other values. This is done through the method call
.
Example:
function nome (pronome) {
return pronome + ':' + this.a + ' ' + this.b;
}
nome.call({a : 'Wallace', b : 'Souza'}, 'Senhor'); // Senhor: Wallace Souza
nome.call({a : 'Guilherme', b : 'Lautert'}, 'Mister'); // Mister: Guilherme Lautert
The function $.proxy
jQuery does something similar, but it is something that already exists natively.
This access there, seems to be linked with adequacy of resources to several audiences, as system have contrast functionality or be suitable to visually impaired etc. xD In doubt look at the questions linked by this tag.
– rray
Removed tag @rray.
– Rafael Kendrik
in that answer I explained a little bit about scopes when using the keyword
new
: http://answall.com/a/85755/13561, may be related– Pedro Sanção
Thank you @Sanction I will read as soon as possible.
– Guilherme Lautert