Im guessing there is no way to get the function caller name in an anonymous function, is there ?
(function()
{
var cls = function()
{
this.foo = function()
{
console.log(arguments.callee.caller); // null
foo1();
}
var foo1 = function()
{
console.log(arguments.callee.caller); // foo
foo2();
}
var foo2 = function()
{
console.log(arguments.callee.caller); // foo1
cls.foo(); // local
}
var cls =
{
foo : function()
{
console.log(arguments.callee.caller); // cls.foo2
}
}
}
return (window.cls = cls);
})();
var c1 = new cls();
c1.foo();
Correct - they're anonymous. If you need to know their names by callee, you'll need to give them a name. Will something like this.foo = function foo() rather than this.foo = function() work for you?
It is possible in recent versions of Chrome and Firefox as follows. I only recommend this for debugging purposes (e.g. javascript tracing in non-production)
var mystery = function() {
var myNameInChrome = /.*Object\.(.*)\s\(/.exec(new Error().stack)[1];
var myNameInFF = new Error().stack.split("#")[0];
}
Related
I have an Javascript object following the Module Pattern
var foo = (function() {
var obj = (function() {
var $button = $('#myButton');
var init = function() {
$button.hide();
};
return {
init: init
};
})();
return { obj: obj };
})();
If I call foo.obj.init(), the button should be hidden, and this does not occur.
I saw different questions here about the assignment of an element to a variable, but I think that the problem is with the object. Can't I access a private variable from a public method?
From my comment:
Do it as part of init... you can just declare the var in order to isolate the scope, and then modify it to actually set the button as part of init
Example:
var foo = (function() {
var obj = (function() {
var $button; //$('#myButton');
var init = function() {
if (typeof $button === 'undefined') {
// i would probably make the selector an argument to `init`
// if i were you.
$button = $('#myButton');
}
$button.hide();
};
return {
init: init
};
})();
return { obj: obj };
})();
I have the following JavaScript code:
var objSample = {
variable: 10,
func1 : function(){
someJQueryPlugin(1, function(){
this.variable; // this doesn't work, don't have access
});
}
}
I have two questions:
1) How can I create an instance of the variable so I can have two stand alone objects, each one with its own unique variable values?
Example:
var obj1 = new objSample();
obj1.variable = 1;
var obj2 = new objSample();
obj2.variable = 2;
2) How can I have access to the variable inside an anonymous function from a jQuery plugin inside a function in the object. passing this didn't help.
var objSample = function(){
this.variable = 10
this.func1 = function(){
someJQueryPlugin(1, function(){
this.variable; <-- this doesn't work, don't have access
});
}
}
also you can extend constructor with params
var objSample = function(options){
this.variable = options.val
this.func1 = function(){
someJQueryPlugin(1, function(){
this.variable; <-- this doesn't work, don't have access
});
}
}
var obj1 = new objSample ({val:1})
var obj2 = new objSample ({val:2})
and to access this from callbacks in different context, enclose this to some variable.
So final code looks like:
var objSample = function(options){
var self = this;
self.variable = options.val
self.func1 = function(){
someJQueryPlugin(1, function(){
self.variable;
});
}
}
You need to change the code from an object literal to a constructor function and ensure that you reference the right this in the func1 function.
function ObjSample() {
this.variable = 10;
this.func1 = function () {
var _this = this;
someJQueryPlugin(1, function () {
_this.variable;
});
}
}
DEMO
In JavaScript I am looking for a way to use bind() on an anonymous and async function.
Example:
exports.foo = function () {};
exports.foo.prototype = {
load : function(id) {
var query = new Parse.Query("SomeObject");
query.get(id).then(function(object) {
this.object = object; // this is the wrong this
});
}
};
I got this working by making the functions non-anonymous, but I think it makes my code look ugly. Especially after having 4 different anonymous functions in a row.
exports.foo = function () {};
exports.foo.prototype = {
load : function(id) {
function _load(object) {
this.object = object;
}
var _loadThis = _load.bind(this);
var query = new Parse.Query("SomeObject");
query.get(id).then(_loadThis);
}
};
Is there a better way?
Well it's not necessarily "better", but you can call .bind() directly after the closing brace of your function instantiation expression:
query.get(id).then(function(object) {
this.object = object; // this is the wrong this
}.bind(this));
A function instantiation expression gives you a function object reference, so putting a . after it and calling bind makes sense. What gets passed to the .then function, therefore, is the return value from the call to .bind.
This syntax is not correct:
exports.foo.prototype = {
load = function(id) {
var query = new Parse.Query("SomeObject");
query.get(id).then(function(object) {
this.object = object; // this is the wrong this
});
}
};
The prototype is an object who's properties are defined as load: function() {}, not load = function() {}.
It should be:
exports.foo.prototype = {
load: function(id) {
var query = new Parse.Query("SomeObject");
query.get(id).then(function(object) {
this.object = object; // this is the wrong this
});
}
};
A simple way to do it is to declare a variable to the correct 'this' and use closuers to keep a reference to it.
exports.foo = function () {};
exports.foo.prototype = {
load : function(id) {
var self = this;
var query = new Parse.Query("SomeObject");
query.get(id).then(function(object) {
self.object = object; // this is the wrong this
});
}
};
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
I have the following Javascript code, and I'm trying to get a callback to work as shown below. I want to see an alert with "123" in it.
var A = function(arg){
this.storedArg = arg;
this.callback = function(){ alert(this.storedArg); }
}
var B = function() {
this.doCallback = function(callback){ callback(); }
}
var pubCallback = function(){ alert('Public callback') };
var a = new A(123);
var b = new B();
b.doCallback(pubCallback); // works as expected
b.doCallback(a.callback); // want 123, get undefined
I understand what is happening but I'm not sure how to fix it. How can I get a callback function that references my a object? In my case, I can make changes to A but not B.
So what you want is to pass the context to the doCallBack.
E.g.
doCallBack = function (callback, callee) {
callback.apply(callee);
}
So then you would do:
b.doCallBack(a.callback, a);
If you cannot modify the B then you can use closure inside A:
var A = function (arg) {
var self = this;
this.storedArg = arg;
this.callback = function () { alert(self.storedArg); }
}
You can create a variable that holds the wanted scope for this by putting it into variable that
var A = function(arg){
this.storedArg = arg;
var that = this; // Add this!
this.callback = function(){ alert(that.storedArg); }
}
Working demo here: http://jsfiddle.net/vdM5t/
I understand what is happening (during the 2nd callback, "this" is b and not a)
No, JS is no class-based language where something could happen. If function(){ alert(this.storedArg); is just called as callback(); (like in b.doCallback), the this keyword points to the global object (window).
To get around that, you'd have to change A to
var A = function(arg){
var that = this; // store reference to the current A object
this.storedArg = arg;
this.callback = function(){
alert(that.storedArg); // and use that reference now instead of "this"
};
}
If you don't expect the storedArg property to change, you could even make it more simple:
var A = function(arg){
this.storedArg = arg;
this.callback = function(){
alert(arg); // just use the argument of the A function,
// which is still in the variable scope
};
}
You need to pass the context you want the callback to execute in:
var B = function() {
this.doCallback = function(callback, context) {
callback.apply(context);
};
};
b.doCallback(a.callback, a); // 123
http://jsfiddle.net/a9N66/
Because inside A.callback function, this does not refer to A but to window object.
var A = function(arg){
this.storedArg = arg;
this.callback = function(){ alert(this.storedArg); }
-----------------------------------^-----------------
}
You can try this,
var A = function(arg){
this.storedArg = arg;
var that = this;
this.callback = function(){ alert(that.storedArg); }
}
var B = function() {
this.doCallback = function(callback){ callback(); }
}
var pubCallback = function(){ alert('Public callback') };
var a = new A(123);
var b = new B();
b.doCallback(pubCallback); // works as expected
b.doCallback(a.callback); // alerts 123
When you do this:
b.doCallback(a.callback);
that just calls a's callback function without telling it to use a for this; so the global object is used for this.
One solution is to wrap that callback up:
b.doCallback(function() { a.callback(); });
Other solutions include binding the callback to a, using jQuery.proxy() (which is just a fancy way of doing my first solution), or passing in a to doCallback and invoking callback on a using apply.
I've got a big Javascript project that I'm trying to refactor into pseudo-classes:
jsFiddle: http://jsfiddle.net/waitinforatrain/7T42w/
var MyNameSpace = {}
MyNameSpace.MyClass = function() {
this.doSomething = function () {
return "hello";
}
this.doSomething2 = function() {
var x = this.doSomething() + " world";
alert(x);
}
this.doSomething2(); //Works fine
$("#mydiv").click ( this.doSomething2 ); //Doesn't work
}
var class = new MyNameSpace.MyClass();
The reason the click event causes an error is that this refers to the #mydiv element.
How am I supposed to design the above so that I can access the element that was clicked but can also call doSomething()?
You need to cache the context reference and wrap the call in a closure:
var MyNameSpace = {}
MyNameSpace.MyClass = function() {
var context = this;
context.doSomething = function () {
return "hello";
}
context.doSomething2 = function() {
var x = context.doSomething() + " world";
alert(x);
}
// You can do this:
context.doSomething2();
// Or this:
$("#mydiv").click(function(e) {
context.doSomething2();
});
}
this.doSomething2 = $.proxy(function() {
var x = this.doSomething() + " world";
alert(x);
}, this);
$.proxy binds the this scope to the context variable inside said function.
Save a reference to this in the outer scope:
MyNameSpace.MyClass = function() {
var that = this;
this.doSomething = function () {
return "hello";
}
this.doSomething2 = function() {
var x = that.doSomething() + " world";
alert(x);
}
this.doSomething2(); //Works fine
$("#mydiv").click ( this.doSomething2 ); //Doesn't work
}
The function assigned to doSomething2 is said to "close over" the variables in its lexical scope and so has access to their values even once MyClass has returned. This allows us to access the doSomething method through the reference to the instance we assigned to that.