Refering to the container object inside event functions - javascript

I have code like this
var MyObj = {
f1 : function(o){ o.onmousedown = MyObj.f2;},
f2 : function(){ MyObj.f1(); }
}
I would like to know how to refer to MyObj without hardcoding it (i.e. this), so I can change object name without changing the code.
I am interested only in litteral object notation.
EDIT:
I didn't get it right. One of the functions was actually onmousedown event, so this wasn't working in it... This will refer to the object that rised event. I wonder is it still possible to refer to MyObj in such case.

Use this.
Eg:
var MyObj = {
f1 : function(){ ... },
f2 : function(){ this.f1(); }}

One of the functions was actually
onmousedown event, so this wasn't
working in it... This will refer to
the object that rised event. I wonder
is it still possible to refer to MyObj
in such case.
One way follows, though it may not be very useful in this case.
var baz = (function(){ // fake a scope
var foo; // foo will exist in the next statement
foo = { bar: function(){ return foo } };
return foo;
})();
The function wrapper, which is executed immediately, acts to keep variables scoped in that block (later versions of JS by Mozilla have improved scoping syntax, but I'm assuming that's not an option). In this simple example, foo is returned and used as the value for baz, but if you were really doing an assignment and didn't care if foo stayed around, then you'd only need the second two lines. But if it were part of a larger expression, then this idiom might come in handy.

Related

How to access operands or arguments in an IF/ELSE? [duplicate]

In Python one can get a dictionary of all local and global variables in the current scope with the built-in functions locals() and globals(). Is there some equivalent way of doing this in Javascript? For instance, I would like to do something like the following:
var foo = function(){ alert('foo'); };
var bar = function(){ alert('bar'); };
var s = 'foo';
locals()[s](); // alerts 'foo'
Is this at all possible, or should I just be using a local object for the lookup?
locals() - No.
globals() - Yes.
window is a reference to the global scope, like globals() in python.
globals()["foo"]
is the same as:
window["foo"]
Well, I don't think that there is something like that in js. You can always use eval instead of locals(). Like this:
eval(s+"()");
You just have to know that actually function foo exists.
Edit:
Don't use eval:) Use:
var functionName="myFunctionName";
window[functionName]();
I seem to remember Brendan Eich commented on this in a recent podcast; if i recall correctly, it's not being considered, as it adds unreasonable restrictions to optimization. He compared it to the arguments local in that, while useful for varargs, its very existence removes the ability to guess at what a function will touch just by looking at its definition.
BTW: i believe JS did have support for accessing locals through the arguments local at one time - a quick search shows this has been deprecated though.
#e-bartek, I think that window[functionName] won't work if you in some closure, and the function name is local to that closure. For example:
function foo() {
var bar = function () {
alert('hello world');
};
var s = 'bar';
window[s](); // this won't work
}
In this case, s is 'bar', but the function 'bar' only exists inside the scope of the function 'foo'. It is not defined in the window scope.
Of course, this doesn't really answer the original question, I just wanted to chime in on this response. I don't believe there is a way to do what the original question asked.
#pkaeding
Yes, you're right. window[functionName]() doesn't work in this case, but eval does. If I needed something like this, I'd create my own object to keep those functions together.
var func = {};
func.bar = ...;
var s = "bar";
func[s]();
AFAIK, no. If you just want to check the existence of a given variable, you can do it by testing for it, something like this:
if (foo) foo();

Unexplained pattern [duplicate]

While investigating google plusone scripts, I've seen following syntax many times:
(0, _.Em)();
Assuming _.Em is a function the statement above would result in calling that function, that's pretty obvious. If, on the other hand, it would be undefined, wouldn't the result be the same as doing simply _.Em() ?
Can anyone shed a light on what's idea behind using such syntax?
Basically, this syntax allows to call _.Em() in the context of the window object instead of _.
Assuming you have this code:
Foo = function() {
this.foo = "foo";
};
Foo.prototype.Em = function() {
alert(this.foo);
};
var _ = new Foo();
Issuing _.Em() will result in Em() being called in the context of _. Inside the function, the this keyword will refer to _, so foo will be printed.
Issuing (0, _.Em)() decouples the method call from the object and performs the call in the global context. Inside the function, the this keyword will refer to window, so undefined will be printed, since window does not have a foo property.
You can test the difference between the two syntaxes in this fiddle.

Can't use own property in JavaScript Object's function

I'm trying to understand the following code:
var x = {
editBox: _editBox,
comboBox: _comboBox,
getExchangeRate: function() {
var r = parseFloat(_editBox.val());
return isNaN(r) ? null : r;
}
}
My question is about the use of _editBox in getExchangeRate().
I'm creating a JavaScript object, which has two value properties and a function property. But why can't the function use editBox? It's undefined if I try.
And how can it use _editBox? It could be much later when the function gets called. I understand there is some work being done under the hood to make it available, but how do I know it will still be valid? Wouldn't it make more sense if I could use editBox instead?
Having come from other languages, that's certainly what seems more logical.
But why can't the function use editBox? It's undefined if I try.
It is a property of the object, not an in-scope variable.
this.editBox will probably work (assuming are you calling getExchangeRate in the right context (i.e. x.getExchangeRate()).
And how can it use _editBox?
Because the variable is in scope.
It could be much later when the function gets called.
That doesn't really matter
how do I know it will still be valid?
You control when and if it gets overwritten.
Because there is no variable such as editBox, but there is _editBox. I think you are looking for
this.editBox.val()
If you call the function as x.getExchangeRate(), then this inside the function will refer to x and you can access its property editBox. See the MDN documentation for more information about this.
Having come from other languages, that's certainly what seems more logical.
JavaScript is not like Java where instance members are automatically in scope of the methods. There is no implicit connection between a function and the object it is a property value of. That's because functions are first-class objects, they don't "belong" to anyone. And JS has lexical scope.
Consider this example:
var name = 'bar';
function foo() {
console.log(name);
}
var obj = {
name: 'baz',
prop: foo
};
As you can see, we defined foo "independently" from obj. obj.name doesn't magically become name inside the function if it is called as obj.prop().

understanding javascript function call and referance

I found this browsing:
What is the difference between a function call and function reference?
After reading the answers there, I did't understand the definition and usage for function references and function calls. Then I searched a lot, but it is still unclear where to use what.
Could you help me understand this by pointing out the differences in concept and usage? I want to make this as a reference for future programers.
Take this for example:
function foo() {
alert('foo');
return 'bar';
}
First of all, what is a function? It's a routine that can be called (or "invoked", or "executed"), and when you do so it usually does something, and returns some value.
So you have a function named foo. You can call it by adding () after its name:
foo();
You can store the return value in a variable, if you assign the result of the invocation to it:
var something = foo();
something === 'bar'; // true
But that's not all you can do with functions in JavaScript. It's a language where functions are first class citizens, so they can be passed around to other functions, and returned from other functions. They can also be stored as variables. For example:
var refToFoo = foo;
Now refToFoo is the same as foo. It's not a copy, it's a reference pointing to the same (internal) function object as foo. So you can use refToFoo just like you would use foo:
var something = refToFoo();
something === 'bar'; // true
refToFoo === foo; // true; they're the same object
Perhaps the most common use to function references is to use them as event listeners:
someElement.onclick = foo;
Note there is no parentheses above. It we used parentheses, foo would be invoked, immediately, and its return value would be assigned to the element's onclick method. Since that function returns a string, nothing would happen if the element were clicked. That's a very common mistake newbies do. Another common one is invoking a function instead of passing a reference to setTimeout:
setTimeout(foo(), 1000); // WRONG - foo is executed immediately
Compare that to:
setTimeout(foo, 1000); // RIGHT - we're passing a reference to the function,
// that will be invoked by the js engine after 1000ms
I hope this helps clarify your doubt.

var self = this?

Using instance methods as callbacks for event handlers changes the scope of this from "My instance" to "Whatever just called the callback". So my code looks like this
function MyObject() {
this.doSomething = function() {
...
}
var self = this
$('#foobar').bind('click', function(){
self.doSomethng()
// this.doSomething() would not work here
})
}
It works, but is that the best way to do it? It looks strange to me.
This question is not specific to jQuery, but specific to JavaScript in general. The core problem is how to "channel" a variable in embedded functions. This is the example:
var abc = 1; // we want to use this variable in embedded functions
function xyz(){
console.log(abc); // it is available here!
function qwe(){
console.log(abc); // it is available here too!
}
...
};
This technique relies on using a closure. But it doesn't work with this because this is a pseudo variable that may change from scope to scope dynamically:
// we want to use "this" variable in embedded functions
function xyz(){
// "this" is different here!
console.log(this); // not what we wanted!
function qwe(){
// "this" is different here too!
console.log(this); // not what we wanted!
}
...
};
What can we do? Assign it to some variable and use it through the alias:
var abc = this; // we want to use this variable in embedded functions
function xyz(){
// "this" is different here! --- but we don't care!
console.log(abc); // now it is the right object!
function qwe(){
// "this" is different here too! --- but we don't care!
console.log(abc); // it is the right object here too!
}
...
};
this is not unique in this respect: arguments is the other pseudo variable that should be treated the same way — by aliasing.
Yeah, this appears to be a common standard. Some coders use self, others use me. It's used as a reference back to the "real" object as opposed to the event.
It's something that took me a little while to really get, it does look odd at first.
I usually do this right at the top of my object (excuse my demo code - it's more conceptual than anything else and isn't a lesson on excellent coding technique):
function MyObject(){
var me = this;
//Events
Click = onClick; //Allows user to override onClick event with their own
//Event Handlers
onClick = function(args){
me.MyProperty = args; //Reference me, referencing this refers to onClick
...
//Do other stuff
}
}
If you are doing ES2015 or doing type script and ES5 then you can use arrow functions in your code and you don't face that error and this refers to your desired scope in your instance.
this.name = 'test'
myObject.doSomething(data => {
console.log(this.name) // this should print out 'test'
});
As an explanation: In ES2015 arrow functions capture this from their defining scope. Normal function definitions don't do that.
var functionX = function() {
var self = this;
var functionY = function(y) {
// If we call "this" in here, we get a reference to functionY,
// but if we call "self" (defined earlier), we get a reference to function X.
}
}
edit: in spite of, nested functions within an object takes on the global window object rather than the surrounding object.
One solution to this is to bind all your callback to your object with javascript's bind method.
You can do this with a named method,
function MyNamedMethod() {
// You can now call methods on "this" here
}
doCallBack(MyNamedMethod.bind(this));
Or with an anonymous callback
doCallBack(function () {
// You can now call methods on "this" here
}.bind(this));
Doing these instead of resorting to var self = this shows you understand how the binding of this behaves in javascript and doesn't rely on a closure reference.
Also, the fat arrow operator in ES6 basically is the same a calling .bind(this) on an anonymous function:
doCallback( () => {
// You can reference "this" here now
});
I haven't used jQuery, but in a library like Prototype you can bind functions to a specific scope. So with that in mind your code would look like this:
$('#foobar').ready('click', this.doSomething.bind(this));
The bind method returns a new function that calls the original method with the scope you have specified.
Just adding to this that in ES6 because of arrow functions you shouldn't need to do this because they capture the this value.
I think it actually depends on what are you going to do inside your doSomething function. If you are going to access MyObject properties using this keyword then you have to use that. But I think that the following code fragment will also work if you are not doing any special things using object(MyObject) properties.
function doSomething(){
.........
}
$("#foobar").ready('click', function(){
});

Categories