a = function (){
var b = 10;
var k = function(){
console.log(b);
}();
}();
The above code will print 10.
var k = function(){
console.log(b);
}
var a = function (){
var b = 10;
k();
}();
This code will print undefined.
Is it possible to print 10 instead? Like binding the scope to k before calling it.
As #Derek answered, you can obviously pass an argument.
Aside from that, you can't transfer or change variable scope, but you can directly manipulate calling context.
As such, you can set b as the property of an object, and set that object as the calling context of whatever function you're calling.
var k = function(){
console.log(this.b);
}
var a = function (){
var obj = {b:10};
k.call(obj);
}();
The .call() method invokes the k function, but sets the first argument you provide as the calling context of the called function.
In fact, you don't technically need to use an object. You could directly set the number as the value to use...
var k = function(){
console.log(this);
}
var a = function (){
var b = 10;
k.call(b);
}();
In strict mode, you'll get the number, but in non-strict, you'll get the Number as its object wrapper.
Really? What have you tried?
var k = function(b){
console.log(b);
}
var a = function (){
var b = 10;
k(b); //Done.
}();
Why does it give you undefined in your second example is because b is not defined. You have to define it first before using the variable b.
var k = function(b){ //<--There, defined. Mission accomplished.
Access into the scope can be granted through eval.
var a = (function() {
var b = 10;
return {
eval: function(s) {
return eval(s);
}
};
})();
var k = function() {
console.log(a.eval("b"));
};
k();
Related
In JavaScript, functions can have properties. Like this:
var f = function(){ console.log("Hello!"); }
f.x = "Whoohoo";
How do I retrieve x from code within f() that might be called long after the variable f goes out of scope?
You could use the property accessor, like the assignment.
var f = function() { console.log("Hello! " + f.x); }
f.x = "Whoohoo";
console.log(f.x);
f();
For stable access, you could use a named function
var f = function foo() { console.log("Hello! " + foo.x); }
// ^^^ >>>>>>>>>>>>>>>>>>>>>>>>>>> ^^^
f.x = "Whoohoo";
console.log(f.x);
f();
If you need some more robust (but also more verbose):
var f = (function(){
var func = () => {
console.log(func.a)
}
return func
})()
f.a = 'Whoohoo'
// trying to break it
var a = f
f = 'somethingelse'
a()
If what you're looking for is to simply access that property from within your function f, you simply reference the function object (either by the variable name if it's a function expression, or by the function name if it's a function declaration).
For example:
var f = function(){ return f.x; };
f.x = "Whoohoo";
// f() => "Whoohoo"
var b = function(){ return f.x; ];
// b() => "Whoohoo"
However, your mention of calling f "long after the variable f goes out of scope" contradicts the lexical scoping of JavaScript. You cannot call the function f unless you do so from the same scope where the function was defined, or from a child scope in reference to where the function was defined. If you are "out of scope", invoking f will throw a reference error.
Let's get a little convoluted. f is already the name of the function by the expression that defines it. And a function is an object by definition in JS. So you can access it and it's properties (such as x) through the f keyword like f.x. Yet, since f is a function, you may use the it as a constructor too and do silly things like...
var f = function(){ console.log("Hello!"); };
f.x = "Whoohoo";
f.prototype.thingy = function(){
console.log(this.constructor.x);
};
var a = new f();
a.thingy();
... and from this point on lets get a little more convoluted. You might event do;
function F(){
F.prototype.thingy = function(){
return this.constructor.x;
};
var obj = Object.create(F.prototype);
console.log("Hello!");
return obj.thingy();
}
F.x = "Whoohoo";
console.log(F());
So you can get the value of a property of the function object F "from within itself" by taking an object instantiated by itself under a closure.
I am trying to get private properties to work in javascript.
var obj = function() {
var a = 0;
this.run = function() {
var q = a;
a += 1;
return q;
};
};
alert(obj.run());
alert(obj.run());
I have a private variable a and a public function run, however when I call it, it throws an error saying obj.run is not a function. Does anyone know what's wrong?
Thanks
You should create instance of your obj
var o = new obj();
console.log(o.run());
console.log(o.run());
Example,
or you can use module pattern, like so
var obj = (function() {
var a = 0;
return {
run: function () {
var q = a;
a += 1;
return q;
}
};
})();
console.log(obj.run());
console.log(obj.run());
Example
the value of this is determined by how a function is called. (Context)
your obj is a function type. It has not been called, not been invoked, or no instance of it has been created yet. Thats y 'this' here refers to window object, not function obj type. Context is 'window' here
this.run = function () {
//code
}
// here the context is window, hence attaches run property to window
// object making run method accessible in global scope.
When you do
obj.run()
// remember 'this' to be window , this statement will not work,
// because obj doesn't have run property.
When you create instance of obj like
var o = new obj(); // context of 'this' is set to function now
so, if you call o.run() // it will work.
this in javascript
I have a self invoking function in javascript and I have another function in the same file where I need the value of a variable that is inside the self-invoking function. How can I do that?
Edit: So I can get one variable, but how about more variables or an array?
And I also have a semicolon at the beggining, how to deal with it:
;(function() {
...
})();
You need to set it as part of the return. Depending upon your exact pattern it could go like
var app =(function(){
var x = 5;
function app() {
}
app.x = x;
return app;
})();
Simple define the variable not in the function but before:
var a = 1;
(function(){ /* do stuff and use a*/})();
function(){
// use a again
}
var x = (function(y) { return y + 2; })(2);
alert(x);
Works just like this:
function addTwo(y) { return y + 2; }
x = addTwo(2);
//Your self invoking func
(function(){
var getStuff = holdsStuff();
console.log(getStuff.a); //getStuff.b, getStuff.cArr etc;
})();
//func in same file that holds the vars that you need.
function holdsStuff(){
var a = 10;
var b = 15;
var cArr = [1,2,3,4,5];
return { a: a, b: b, cArr: cArr};
}
I just write a test html file to learn about object in javascript. The code is as follows
in script tag
<script type="text/javascript">
var obj = new ParentFn();
var obj2 = new AnotherParentFn();
var temp;
function initer()
{
temp = obj.Adding();
obj2.caller();
}
function ParentFn()
{
this.a = 10;
this.b = 20;
}
function AnotherParentFn()
{
this.a = 30;
this.b = 50;
}
AnotherParentFn.prototype.caller = function()
{
var self = this;
temp();
}
ParentFn.prototype.Adding = function()
{
var self = this;
document.getElementById("id_div1").innerHTML = " Method Called and Result of a+b is " + (self.a + self.b);
}
</script>
In body i use
<button onclick="initer()"> Click here to test </button>
<div id="id_div1"></div>
Problem is when AnotherParentFn.prototype.caller is called from initer() function temp variable is still undefined. What is wrong with the code??
My task is to assign the function ParentFn.prototype.Adding in a global variable and call the global variable from AnotherParentFn.prototype.caller function. How to achieve it?
You don't need to save it as a global variable. It's already saved in ParentFn.prototype. All you need to do is invoke it with .call and pass in your desired receiver. You can implement AnotherParentFn.prototype.caller like this:
AnotherParentFn.prototype.caller = function()
{
ParentFn.prototype.Adding.call(this);
}
This way you can get rid of temp completely. You also don't need to assign this to a local var self everywhere.
Parentheses are used to execute a function.
When you assign the value to temp, you are calling the function and assigning the result (undefined) to temp. To store a reference to the function in temp, omit the parentheses.
temp = obj.Adding;
By writing temp = obj.Adding(); it stores the return value. not function pointer in temp. Use this
function initer()
{
temp = obj.Adding;
obj2.caller();
}
First of all, the reference to obj.Adding is not assigned properly; it should be this (without parentheses):
function initer()
{
temp = obj.Adding;
obj2.caller();
}
Then, inside AnotherParentFn.prototype.caller itself, you must pass the current object as this explicitly during the invocation by using .call():
AnotherParentFn.prototype.caller = function()
{
temp.call(this);
}
I understand the general idea behind the this keyword but I'm having trouble figuring out what it actually refers to in practice. For example, in both these example exercises, I guessed the wrong number.
for question1, I said that the alert would be '5', because it is referring to the this.x outside the anonymous function in the function.
In question2, I thought the alert would be 5 because this line
var alertX = o.alertX;
would bind the value 5 for property x inside the variable o to the new variable 'alertX' which becomes the function call in the next line: alertX();
Can you explain why I'm wrong?
var question1 = function() {
this.x = 5;
(function() {
var x = 3;
this.x = x;
})();
alert(this.x);
};
var answer1 = 3;
var question2 = function() {
this.x = 9;
var o = {
'x':5,
'alertX':function() { alert(this.x); }
};
var alertX = o.alertX;
alertX();
}
var answer2 = 9;
In the first case, when you invoke a method with no explicit receiver this is the Global object (the window in a web browser).
Similarly in the second case: even though the function is defined on the object, and you are inside another, by invoking the function with alertx() the this is set to the Global/window.
In short:
For foo.bar(), the this inside of bar will be foo.
For bar(), the this will be the Global object.
This includes so-called "self-invoking lambdas", i.e. (function(){ ... })().
For bar.call(whee) and bar.apply(whee), the this will be whee (because that's what these methods do).
Another example:
var o1 = { name:"o1", f:function(){ console.log(this.name) } };
var o2 = { name:"o2" };
o2.gogogo = o1.f;
o2.gogogo(); // Will output "o2"
These are good examples of how interesting this becomes in Javascript. this always refers to the context in which it was invoked / called, not simply where it is at that moment! question2 is a perfect example of it.
I'm assuming you are invoking these globally like so:
question1();
question2();
In question1:
You have an anonymous function that is ran after you first set x to 5. This anonymous function if not set to a variable, inside a function etc, would have this set to the global variable of window. But you have it within a function & set to variable question1. So when it runs itself, it sets this's (which is question1 function) x variable to 3.
In question2:
X is originally set to 9, this being question2 in this instance. Now the part that is throwing you off is that, even though within the o {} object you set x : 5. And your alertX function is calling this.x. All of this would lead you to think it will alert 5! But you are invoking your alert function outside of the o {} object, hence the this refers to question2 function again!
Put the following into your browser's console
var x = -1, log = function(){ // set up some stuff
if(console) if(console.log) return console.log.apply(console, arguments),undefined;
return alert(arguments.join(', ')),undefined;
},
question1 = function() {
this.x = 5; // question1.x is 5
(function() { // anonymous function fires in global 'window'
var x = 3; // so window.x is now 3
this.x = x; // this is window
})();
log('ans1',this.x,this); // see below
},
question2 = function() {
this.x = 9; // question2.x is 9
var o = {
'x':5, // o.x is 5
'alertX':function() { log('ans2',this.x,this); }
};
var alertX = o.alertX; // alertX === o.alertX
alertX(); // being called in global scope
// to make alertX have scope of question2
this.alertX = o.alertX; // this is question2
this.alertX(); // so we're calling from question2
},
a1 = new question1(), // note the new operator
a2 = new question2();
undefined;
And you'll get
ans1 5 question1
ans2 3 Window
ans2 9 question2