Javascript Nested Functions Scope - javascript

I have the following javascript object, somewhat pseudocode:
{
dateField: new Date(),
addMinutes:function(numMinutes)
{
CallWebService(numMinutes, function{alert(this.dateField; });
}
}
The problem is the scope of the callback function in CallWebService doesn't see the dateField property of the object. Is there a way I can access it? Thanks!

You need to preserve the context (the this value) of the addMinutes function.
There are several ways to achieve it, the most easy one is to simply store a reference of this on a variable, that variable will be available to the scope of the callback function, e.g.:
var obj = {
dateField: new Date(),
addMinutes: function(numMinutes) {
var instance = this;
CallWebService(numMinutes, function () {
alert(instance.dateField);
});
}
};

The issue is that the callback is likely setting the scope of the callback function, if you use apply or call you can force the scope. You can do this with something like this:
{
dateField: new Date(),
addMinutes: function (numMinutes) {
var self = this;
var success = function () {
alert(this.dateField;);
};
CallWebService(numMinutes, function () { success.apply(self); });
}
}

You can access any property(i.e variable or function) of an object inside that object scope by using the dot(.) operator. So you can use like this:
var obj = {
dateField: new Date(),
addMinutes: function(numMinutes) {
callWebService(numMinutes, function() {
alert(obj.dateField);
});
}
}
Here 'dateField' variable of the object 'obj' is accessible inside that object scope using the dot operator like 'obj.dateField'. I think this will help you to solve your problem, let me know if you are not clear with the code shown above.

Related

Calling a nested function by name

I am looking for a way how to call a nested function when I have its name as string. I am writing a function that returns an object that will do some processing by calling functions that are part of its closure and are intentionally inaccessible from the global scope. The code goes something like this:
function makeHandler() {
function case1() {
...
}
function case2() {
...
}
let handler = {}
handler.handle = function(div) {
let divCase = div.getAttribute("data-case");
//divCase is now either "case1" or "case2". I want to call the correct function. I have:
({case1: case1, case2: case2}[divCase])()
}
return handler
}
let h = makeHandler()
h.handle(someDiv)
I find this approach unsatisfying, if I add case3 I will have to update the handle function. I'd think that the functions case1 and case2 must be part of some context, just like makeHandler is part of the global context and accessible as property of the window object.
I am aware of the very similar 10 year old question: Calling nested function when function name is passed as a string and I've seen other articles with similar recommendation to what I am doing -- create an object where properties are function names and values are functions themselves. I am looking for a more 'generic' solution.
I like using this pattern:
function makeHandler() {
const cases = {
case1: function () {},
case2: function () {}
}
let handler = {}
handler.handle = function(div) {
let divCase = div.getAttribute("data-case");
if (!cases[divCase]) throw 'bad case name';
cases[divCase]();
}
return handler
}

How to access javascript object Arrays inside prototype function

Hello I'm having a problem that haven't searched before
I'm trying to recode my javascript used for accessing google api's so that I can create objects to access them in further projects .
Let me Explain the Code because I'm not posting the original code here below code is the just like an example of my code
I'm a having constructor function and it has arrays declared with 'this' keyword. and Then I have an prototype of the constructor function and inside that prototype I had a nameless function created to access jquery requested output from a server.But I'm unable to access those array objects
function cons(){
this.objectarray = [];
}
cons.prototype.profun = function(){
this.objectarray[0] = 'working';
alert(this.objectarray[0]);//Access is possible
$.get('requesting url',{'parameters'},function(data){
alert(this.objectarray[0]);//Access is not possible
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
when I try to access the object inside that jquery function I'm getting this error from browser console
TypeError: this.YouTubeTitle is undefined
You have to cache the this object so that when you use the this keyword in your callback, it refers to the correct object:
function cons(){
this.objectarray = [];
}
cons.prototype.profun = function(){
// this is volatile in JavaScript. It's meaning changes depending
// on the invocation context of the code that contains it. Here,
// this will refer to your "cons" object instance.
var self = this;
this.objectarray[0] = 'working';
alert(this.objectarray[0]);
$.get('requesting url','parameters',function(data){
// But here, "this" will be bound to the AJAX object
alert(self.objectarray[0]); // <-- Use cached this object
});
};
//*************************
var c = new cons();
c.profun();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Inside the GET-Callback there is a local this which overrides your Prototype-Function's this. Store the outer this in a named variable and call that inside the callback and you will be fine.
let outerThis = this;
somethingWithCallback(function(){
alert(outerThis);
})
I've found solution for this from one of the comments
the below code is the solution
function cons(){
this.objectarray = [];
}
cons.prototype.profun = function(){
this.objectarray[0] = 'working';
alert(this.objectarray[0]);
$.get('requesting url',{'parameters'},function(data){
alert(this.objectarray[0]);
}.bind(this));//by binding 'this' we can access the 'objectarray'
}
Thanks for the solution #Redu from comments
You can wrap your anonymous function with $.proxy to persist the outer this context.
function cons() {
this.objectarray = [];
}
cons.prototype.profun = function() {
this.objectarray[0] = 'working';
alert(this.objectarray[0]);
$.get('requesting url', {
'parameters'
}, $.proxy(function(data) {
alert(this.objectarray[0]);
}, this));
}

Closures Cannot access a function

I am trying to understand closures. In the code below, I create an instance of the constructor function Ninja and I call the instance kawazaki. I expected to be able to access the methods of Ninja. However, I am getting a TypeError: Object #<Ninja> has no method 'feints' instead.
The output I expected was 1.
Here is my code:
function Ninja() {
var feints = 0;
function getFeints() {
return feints;
}
function feints() {
feints++;
}
}
var kawazaki = new Ninja();
kawazaki.feints();
console.log(kawazaki.getFeints());
Try this instead:
var kawazaki = new Ninja;
kawazaki.feints();
alert(kawazaki.getFeints());
function Ninja() {
var feints = 0;
this.getFeints = function () {
return feints;
};
this.feints = function () {
feints++;
};
}
You need to assing public properties to this within the constructor function.
The scope of the functions getFeints and feints is limited to the function Nija. As you can not access to variables declared in a function, you can not access to those functions.
To be able to execute kawazaki.feints(), you have to "attach" the function to the Ninja function, as an object (which a function also is)
You will find in these resources several ways to achieve that, and also some deeper explanations:
How do JavaScript closures work?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
Closure is a very simple yet largely misunderstood topic.
function Ninja() {
var feints = 0;
function getFeints() {
return feints;
}
function feintsInc() {
feints++;
}
}
You have defined the closure alright but please note that a closure is not actually a method of the object. In order to get your desired output you need to call the closures just before closing the object.
feintsInc();
getFeints();
If,however, you wish to do it as
kawazaki.feintsInc();
you need to use this keywords in your function to get the functions assigned to the object.
Note,make sure your functions and variable names don't overlap.

Does JavaScript have a variable for items declared in the function's scope? [duplicate]

This question already has answers here:
How can I access local scope dynamically in javascript?
(4 answers)
Closed 9 years ago.
Does JavaScript have a variable for items declared in the function's scope? I would like to access items declared inside a function using an associative array.
For example I can do the following with items at the global scope
var globalVar = "hi";
var myFunction = function () {
alert(window["globalVar"]);
};
But I would like to do a similar thing with variables declared inside a function
var myFunction = function () {
var funcVar = "hi";
alert(func["funcVar"]);
};
I realise doing such a thing isn't necessarily a good thing and I am doing the below instead, but I am still interested if JavaScript has such a variable.
var myFunction = function () {
var func = {funcVar : "hi" };
alert(func["funcVar"]);
};
This question has been asked and answered many times. No, in JavaScript there is no local object containing local variables as properties (in the way that for instance, in browser environments the window object contains global variables as properties).
Depending on what you are trying to accomplish, there are probably many alternative ways to attack it, including the one you are using now.
Duplicate of Javascript: Get access to local variable or variable in closure by its name, How can I access local scope dynamically in javascript?, Javascript local variable declare.
Perhaps you could assign properties to the function object itself, and reference those?
var myFunction = function() {
myFunction.funcVar = 'hi';
alert(myFunction['funcVar']);
};
It is not exactly the answer to your question, but it's the best way I can think of to access local variables as properties of an object. Note that in this method these variables will be visible outside the function in the same manner (that is, looking up the properties of the function).
If you really needed those properties to be hidden, you could hide them within a closure, like so:
var myFunction = function() {
(function hidden() {
hidden.funcVar = 'hi';
alert(hidden['funcVar']);
})();
};
Functions are just special objects that can be invoked. You can set properties of a function, and get them later.
var a = function () {
alert(a.testingVar);
};
a.testingVar = "asdf";
a();
DEMO: http://jsfiddle.net/gEM7W/
Although I don't see a reason/need to do this. You could always use a closure to keep local variables specific to a function. For example:
var a = (function () {
var obj = {
testingVar: "asdf"
};
return function () {
alert(obj.testingVar);
};
})();
a();
DEMO: http://jsfiddle.net/gEM7W/1/
You don't really have associative arrays. You have indexed arrays and you have objects.
In the future, there will be an iterator which will happily traverse both, without any side-effects. At that point, perhaps people will forget the difference.
However, the properties still wouldn't be order-based:
$arr = array(0, 1, "name"=>"Bob", 3);
In another language might get you an array where the keys are: 0, 1, "name", 3
In JS, you'd get 0, 1, 2, "name" (or "name", 0, 1, 2).
So stick with indexed arrays and objects with properties.
That said, you've got multiple options.
var myFunc = function () {
var private_data = {
name : "Bob",
age : 32
};
return {
getName : function () { return private_data.name; /* or private_data["name"] if that's really what your heart longs for */ },
get : function (key) { return private_data[key] || null; },
set : function (key, val) { private_data[key] = val; }
};
};
Now everything is private, and you can access them by property-name, using dot or bracket notation.
If they can be public, and the function is always going to be called the same thing (ie: not a constructor making an instance) then you can attach yourself to the actual function:
var myFunc = function () {
myFunc.name = "Bob";
myFunc["age"] = 32;
return {
get : function (key) { return (myFunc.hasOwnProperty(key)) ? myFunc[key] : null; }
};
};
Downside (or upside) is that myFunc is the public name. As such, these properties are publicly accessible.
Going the first route, you don't even need to declare a variable. You can just use the object you pass into a function.
var myFunc = function (dataObj) {
return {
getName : function () { return dataObj.name; },
setAge : function (val) { dataObj["age"] = val; }
};
};
var bob = myFunc({ name : "Bob" });
bob.setAge(32);
Now everything's private and I didn't even have to declare anything.
Closure keeps the object in play as long as there's a publicly accessible function that's returned, which still has access to that particular instance of the function call.
Once you figure out closures, this becomes a non-issue.

Executing Javascript functions by reference

I'm wondering if any of yall have any insight as to how one could execute a function by reference in javascript.
http://mootools.net/shell/yL93N/1/
Any discussion would be cool.
-Chase
looking at your mooshell, the way i'd handle it in mootools is this:
http://mootools.net/shell/yL93N/10/
var proxyFunction = new Class({
message: "hello",
Binds: ['passByReference','sayit'],
passByReference: function(func) {
// console.log(this, this[func]);
if (this[func] && $type(this[func]) === "function")
this[func]();
},
sayit: function() {
alert(this.message);
},
killit: function() {
document.write('we\'re dead');
}
});
$('tryit').addEvent('change',function(e){
new proxyFunction().passByReference(this.get('value'));
});
// or have a permanent proxy instance if you call methods of the class often and need it to change things.
var proxy = new proxyFunction();
$('tryit').addEvent('change',function(e){
proxy.passByReference(this.get('value'));
});
the advantage of doing so is that all your proxied functions are behind a common object, don't pollute your window namespace as global variables and can share data that relates to the event.
Not exactly sure what you mean, but you can do this:
var func = window.alert;
var args = ["hello world"]
func.apply(window, args)
Globally-defined functions (and variables) are visible as members of the global window object.
Members of an object can be fetched by name using the square bracket notation: o['k'] is the same as o.k. So, for your example:
var function_name= $(this).val();
window[function_name]();
Like this?
function blah() {
...do stuff
}
myref = blah
myref()
The best way is to do:
func.call();
Function variables in JavaScript already are references. If you have a function:
var explode = function() { alert('boom!'); };
You can pass explode around as an argument, and it's only passing a handle to that function, not the entire function body.
For proof of this, try:
explode.id = 5;
var detonate = explode;
alert(detonate.id); // => 5
explode.id = 6;
alert(detonate.id); // => 6
functions are first class objects in Java Script. Effectively this means that you can treat it very much as if it were a variable, and pass it anywhere that you would expect a variable.
e.g.
var myFn = function() { alert('inside anonymous fn'); }
function callMyFn(paramFn)
{
paramFn();
}
callMyFn(myFn); //inside anonymous fn
function MyFnHolders(argFn)
{
this.argFn = argFn;
this.fieldFn = function() {
alert('inside fn field');
}
}
var myFnHolders = new MyFnHolders(myFn);
myFnHolders.argFn(); //'inside anonymous fn'
myFnHolders.fieldFn(); //'inside fn field'
//etc
so passing a function by ref can be done simply by assigning it to a variable and passing it around.
Here's one with a closure for your arguments...
function Runner(func, args) {
return function() { return func.apply(window, args); };
}
var ref = new Runner(window.alert, ["hello world"]);
ref();

Categories