win1 = window.open and win1.close() in different functions not working - javascript

I have 2 separate functions in a javascript.
Function one opens a window with
win1 = window.open (....);
Function two closes the window:
win1.close();
If those actions are in one function it is working but not in the separate functions as above. It somehow looses the object win1 from one function to another.
Any help would be very welcome!

You need to declare the win1 variable outside both functions so that they're in the variable scope of both.
var win1; // This variable is available in the variable scope of any
// ...functions nested in the current scope.
function f1() { // This function has access to its outer variable scope
win1 = window.open(); // ...so it can access the "win1" variable.
var foo = 'bar'; // This variable is not available in the outer scope
} // ...because it was declared inside this function.
function f2() { // This function has access to its outer variable scope
win1.close(); // ...so it can access the "win1" variable.
var bar = 'baz'; // This variable is not available in the outer scope
// ...because it was declared inside this function.
alert(foo); // Gives a ReferenceError, because "foo" is neither in the
// ...current, nor the outer variable scope.
}
f1(); // Invoke f1, opening the window.
f2(); // Invoke f2, closing the window.
alert(foo); // Would give a ReferenceError, because "foo" is in a nested scope.

You can also define win1 globally:
window.win1 = window.open(...);

You could also declare a global variable. You can then just use it anywhere in your scripts.
var win = window.open("URL"); // or window.win = window
win.open();
win.close();
You have to pass win1 as a variable to both functions or have it outside those 2 functions.
function somethingHappened() {
var url = "http://....";
var win = window.open(url);
one(win,url);
two(win);
}
function one(win,url) {
win.open(url);
}
function two(win) {
win.close();
}

Related

calling a function from its string name on Window object

Why is the test fuction declaration not found in the window object? Thanks
!function(){
function test(){
console.log("testing");
}
var check = window["test"]
console.log(check); //undefined
}();
Since function test() is local to the scope of the toplevel function expression, it's not bound to window, the global scope. You can refer to it as a local variable:
!function() {
function test() {
console.log('testing')
}
console.log(test)
}()
Or bind it directly to window for a global variable:
!function() {
window.test = function test() {
console.log('testing')
}
var check = window['test']
console.log(check)
}()
You cannot access the local scope as a variable - see this question for more details.

Javascript's Function constructor - scope issues?

This code new Function('fn', 'fn()') creates anonymous function which has param and (in this case the param is a function) executed.
Doing console.log(new Function('fn', 'fn()')) shows the output :
function anonymous(fn)
{
fn()
}
Now , the docs states :
Note: Functions created with the Function constructor do not create
closures to their creation contexts; they always are created in the
global scope. When running them, they will only be able to access
their own local variables and global ones, not the ones from the scope
in which the Function constructor was called. This is different from
using eval with code for a function expression.
Ok.
So why does this code yields 1 and not 44 ?
var a = 44;
function myFunc()
{
var a = 1;
function f()
{
alert(a)
}
new Function('fn', 'fn()')(f);
}
myFunc();
Why ?
What about this line above ?
they will only be able to access their own local variables and global
ones, not the ones from the scope in which the Function constructor
was called
It looks like the f is closure over the parent a , but how come ? it suppose to be run at global , and able to access local and global only !
What am I missing ?
Because you're invoking function f, which is a normal function that does create a closure.
The documentation refers to this:
var a = 44;
function myFunc()
{
var a = 1;
new Function('fn', 'alert(a)')(); //shows 44, not 1
}
myFunc();
In your example you call f function that defined inside myFunc function. Does not matter where you called it from. So you called you anonymous function that is defined in global scope and see a = 44, anonymous function called f function that is defined in myFunc scope and see a = 1.
I'm not sure what exactly you want to achieve with this code, but if you need 44 in your f you need to pass it there as an argument.
var a = 44;
function myFunc() {
var a = 1;
function f(myArgument) {
alert(myArgument)
}
new Function('fn', 'fn(a)')(f);
}
myFunc();

Why nested local function binds `this` to window instead of the parent

I was reading some documentation about javascript and stumbled upon the following code example:
var o = {
value: 1,
outer: function () {
var inner = function () {
console.log(this); //bound to global object
};
inner();
}
};
o.outer();
It outputs window.
I cannot figure out why is the this keyword bound to the global object (window) instead of the parent object (outer).
If you want to access outer from inner's scope, you have to pass the outer's this (which is just like passing outer itself) to its local inner function as an argument. So, as expected:
var o = {
value: 1,
outer: function () {
var inner = function (that) {
console.log(that); //bound to global object
};
inner(this);
}
};
o.outer();
outputs outer.
Isn't it a bit of a nonsense that in outer's scope this is bound to the object itself (i.e. outer), while in the inner's scope, which is local to outer, this is re-bound to the global object (i.e. it overrides outer's binding)?
The ECMAScript specs states that when entering the execution context for function code if the «caller provided thisArg» is either null or undefined, then this is bound to the global object.
But the following:
var o = {
outer: function () {
var inner = function () {
console.log('caller is ' + arguments.callee.caller);
};
inner();
}
}
outputs the object outer itself:
caller is function () {
var inner = function () {
console.log('caller is ' + arguments.callee.caller);
};
inner();
}
On a side, but probably relevant, note:
In strict mode the first code snippet outputs undefined instead of window.
This is because this is set when the function is run, not when it's defined.
For example:
var o = {
func: function(){
console.log(this);
}
};
When you call o.func(), you are doing so in the context o, so it works as expected.
Now let's say you do this:
var f = o.func;
f();
This will not work as expected. This is because when you call f(), it doesn't have any context attached to it, so this will be window.
You can fix this by using .call to change the value of this.
var f = o.func;
f.call(o); // sets `this` to `o` when calling it
That's just how it the language works.
Every time a function is called, this will be reset. In a nested (inner) function it does not inherit the value from the enclosing scope the way other (explicitly declared) variables are.
By default this will be set to window, unless the function is invoked as:
myObj.func(arg1, ...) or
func.call(myObj, arg1, ...) or
func.apply(myObj, [arg1, ...])
in which case this will be equal to myObj
A function called any other way, even if it was originally defined as a property of an object (i.e. var func = myObj.func; func() will use window.
There's also a utility function called .bind which wraps a function reference in such a way that you can provide a specific value which will always be used as this:
var myFunc = myObj.func; // obtain reference to func
var bound = myFunc.bind(someOtherObj); // bind it to "someOtherObj"
bound(); // this === someOtherObj
bound.call(myObj) // this still === someOtherObj

What scope are variables globally defined by "var"?

In Javascript, if I declare variables with var in javascript outside of a function
var foo = 1;
var bar = 2;
function someFunction() {
....
}
are those variables within the scope of the document or the window? Furthermore, why does this matter? I know that if one declares a variable without var, then the variable is global.
Is there a simple way for me to test whether a variable falls within the scope of the document or the window?
var limits the scope of a variable to the function it was defined in, so variables defined at the top level with var will effectively have global scope.
If you assign a value to a variable that hasn't been scoped with var then it becomes global regardless of where you define it.
There is a good article on javascript scopes here: What is the scope of variables in JavaScript?
When you declare a function in JavaScript, it creates a scope.
When you declare a variable, it must have a var. The var determines what scope it belongs and where it is visible. If it has no var, then it's an "assignment" to a variable and the browser assumes that a variable with that name exists in the outer scopes.
When an assignment happens, the browser searches outwards until it reaches the global scope. If the browser does not see the assigned variable in the global scope, it will declare it in the global scope (which is not good)
for example, take the following as a demo of scope visibility and not actual working functions:
//global variables
var w = 20
var x = 10
function foo(){
function bar(){
//we assign x. since it's not declared with var
//the browser looks for x in the outer scopes
x = 0;
function baz(){
//we can still see and edit x here, turning it from 0 to 1
x = 1;
//redeclaring a variable makes it a local variable
//it does not affect the variable of the same name outside
//therefore within baz, w is 13 but outside, it's still 20
var w = 13;
//declaring y inside here, it does not exist in the outer scopes
//therefore y only exists in baz
var y = 2;
//failing to use var makes the browser look for the variable outside
//if there is none, the browser declares it as a global
z = 3;
}
}
}
//w = 20 - since the w inside was "redeclared" inside
//x = 1 - changed since all x operations were assigments
//y = undefined - never existed in the outside
//z = 3 - was turned into a global
var foo = 1;
window.foo === foo;
JavaScript is a functional language and therefore any variable declared inside the scope of a function is only available in that function.
JS will actually go through each functions scope and look for a variable declared.
function setGlobal() {
bar = 1; // gets set as window.bar because setGlobal does not define it
}
setGlobal();
// logs true and 1
console.log(window.bar === bar, bar); ​
http://jsfiddle.net/kXjrF/
So...
function logGlobal() {
var bar;
console.log( foo, window.foo ) // undefined, undefined
function setGlobal() {
// window.foo is now set because logGlobal did not define foo
foo = 1;
bar = 2; // logGlobal's bar not window.bar
function makePrivate() {
var foo = 3; // local foo
console.log( foo ); // logs 3
}
makePrivate(); // logs 3
}
setGlobal();
console.log( foo, window.foo ); // logs 1, 1
}
as JavaScript has only function scope, variables defined by the var keyword are scoped to the containing function.
you can easily check for global scoping by opening the JavaScript console in the browser (or directly in your code), and typing:
varRef && console.log(varRef)

Javascript scope issue: variable not being identified

I have two functions, one function calling the other.
Below is a simple analogy I created of the structure of code which I have:
function test1(){
alert(a);//a is not identified here even when test1() is called under test2 which has a defined in scope
alert(b);//b is identified here
}
function test2(){
var a = 'a';//Defining a
test1();//Calling test1()
}
var b = 'b';
test2();
As per the code above, function test1() is able to identify variable b but not variable a.
My question is that why variable a is not in the scope of test1 function even when we are calling test1() inside test2() which defines variable a?
Thanks in advance.
Functions remember their scope chain at the time they're being created, not at the time they're called.
Note that b gets "hoisted", so your code actually does this:
var b; // push b on scope chain
function test1(){ // store scope chain [b]
alert(a);
alert(b);
}
function test2(){ // store scope chain [b]
var a; // push a on scope chain
a = 'a';
test1(); //Calling test1() which still has scope chain [b], not [b,a]
}
b = 'b';
test2();
your expectation is wrong about the scope of the variables,
according to your code b is a global variable to 2 functions and a is in the scope of test2 function only because it is defined withing test2,
If you want something like you expected you can define test1 function in test2 scope like this,
function test2(){
var a = 'a';
test1();
function test1(){
alert(a);
alert(b);
}
}
var b = 'b';
test2();
JavaScript has 'function scope' which means that anything defined in a function is not visible outside of the function. So variable 'a' is not visible outside of test2. However, variable 'b' is a global variable so it is visible in every scope.
Function scope also means that inner functions get access to things defined in the outer function but that doesn't come in to play here...test1 is called from within test2 but it's not an inner function of test2. To see this in action you'd need to define the body of the test1 function within test2...
function test2(){
var a = 'a';//Defining a
test1();//Calling test1()
function test1(){
alert(a);//a is identified here because of function scope
alert(b);//b is identified here because it's global
}
}
It is a good practice to call the functions with arguments. This will make your code easily readable and maintainable. Just adding arguments to the functions make the code working:
function test1(a,b){
alert(a);
alert(b);
}
function test2(b){
var a = 'a';
test1(a,b);
}
var b = 'b';
test2(b);
If you don`t want to use arguments in the function declarations, a solutions is to use the arguments object inside the code:
function test1(){
alert(arguments[0]);
alert(arguments[1]);
}
function test2(){
var a = 'a';
test1(a,arguments[0]);
}
var b = 'b';
test2(b);
If you want you can make the arguments with default values. Since in JavaScript you can`t do it in the function argument list, it is done in the body of the function:
function test1(a,b){
a = a || 'a';
b = b || 'b';
alert(a);
alert(b);
}
function test2(b){
var a = 'a';
test1(a);//here b is not passed to the function and b will get the default value
}
var b = 'some new string for b';
test2(b);
Live on jsfiddle
According to your functions you have declared and defined the variable "a" within the function "test2()" so the scope of the variable "a" is restricted within that function itself and accessing the variable will return "undefined". But it is not in the case of the variable "b" which is declared and defined globally, So it can be accessed any where in the script part.
hope this helps you.

Categories

Resources