Calling function inside object using bracket notation - javascript

If i have a function defined inside some object as in :
var myobject={
myfunction:function(){//mycode here}
}
usually you can access the function using:
myobject.myfunction()
but what if i want to use
myobject["myfunction"]
trying so , actually the function did not get called , how can i call the function using brackets notation ?

Use it like. You were very close
myobject["myfunction"]();
You can also do this
var myfuncname="myfunction";
myobject[myfuncname]();

The two forms
myobject.myfunction;
and
myobject["myfunction"];
are equivalent as long as you only use a fixed string to access the member (using a computed value is a different matter, then you must use the second form). Both lines result in the function-object-member myfunction which you can assign to a variable if you like, and calling that:
var myfunc = myobject.myfunction;
myfunc();
Note that assigning it to the variable breaks the this variable, so you might not want to do that if you're doing OOP.
And as you noted, calling a function means adding () with an argument list afterwards, it doesn't matter that the function is acquired through an expression, so either:
myobject.myfunction();
or
myobject["myfunction"]();

Related

Confused about when to use `bind` in an Event Handler

The following successfully prints 'foo'.
var obj = {
name: 'foo',
printName: function printName() {
console.log(this.name);
}
};
var printButton= document.getElementById('printIt');
printButton.addEventListener('click', function(){
obj.printName();
});
The following doesn't, however:
printButton.addEventListener('click', obj.printName() );
I know the solution... simply use bind so that we're referencing the obj object. i.e:
printButton.addEventListener('click', obj.printName.bind(obj) );
Why then don't we need to use bind in the first example. I don't know why wrapping obj.printName() function call in the anonymous function results in the console.log correctly referencing and printing this properly, but when called directly after click, you needs to use bind
Alright, I commented with some good information on this question so I might as well answer!
Functions are first class
Okay, let's starts with some fundamentals of javascript that is very dissimilar to some other programming languages: in javascript functions are first class citizens--which is just a fancy way of saying that you can save functions into variables and you can pass functions into other functions.
const myFunction = function () { return 'whoa a function'; }
array.map(function () { return x + 1; });
And because of this wonderful feature, there is a big difference between the expressions:
Expression 1
obj.printName
and
Expression 2
obj.printName();
In expression 1: the function isn't being invoked so the value of the expression is of type function
In expression 2: the function is being invoked so the value of the expression is what the function returns. In your case, that's undefined
addEventListener
The method addEventListener takes in two arguments:
a string of the type of event
a function that will be run when the event fires.
Alight, so what does that mean?
When you call
// doesn't work
printButton.addEventListener('click', obj.printName() );
you're not passing a value of type function to the addEventListener method, you're actually passing undefined.
// works
printButton.addEventListener('click', obj.printName.bind(obj) );
then works (for one reason) because the second argument is actually of type function.
What does bind do? Why does it return a function?
Now we need to discuss what bind actually does. It related to the pointer* this.
*by pointer, I mean a reference identifier to some object
bind is a method that exists on every function object that simply binds the this pointer of a desired object to the function
This is best shown by an example:
Say you have a class Fruit that has a method printName. Now that we know that you can save a method into a variable, let's try that. In the example below we're assigning two things:
boundMethod which used bind
unboundMethod that didn't use bind
class Fruit {
constructor() {
this.name = 'apple';
}
printName() {
console.log(this.name);
}
}
const myFruit = new Fruit();
// take the method `printName`
const boundMethod = myFruit.printName.bind(myFruit);
const unboundMethod = myFruit.printName;
boundMethod(); // works
unboundMethod(); // doesn't work
So what happens when you don't call bind? Why doesn't that work?
If you don't call bind in this case, the value of the function that gets stored into the identifier unboundMethod can be thought to be:
// doens't work
const unboundMethod = function() {
console.log(this.name);
}
where the contents of the function is the same contents of the method printName from the Fruit class. Do you see why this is an issue?
Because the this pointer is still there but the object it was intended to refer to is no longer in scope. When you try to invoke the unboundMethod, you'll get an error because it couldn't find name in this.
So what happens when you do use bind?
Loosely bind can be thought of as replacing the this value of function with the object you're passing into bind.
So if I assign: myFruit.printName.bind(myFruit) to boundMethod then you can think of the assignment like this:
// works
const boundMethod = function() {
console.log(myFruit.name);
}
where this is replaced with myFruit
The bottom-line/TL;DR
when to use bind in an Event Handler
You need to use Function.prototype.bind when you want to replace the thises inside the function with another object/pointer. If your function doesn't ever use this, then you don't need to use bind.
Why then don't we need to use bind in the first example?
If you don't need to "take the method" (i.e. taking the value of type of function), then you don't need to use bind either Another way to word that is: if you invoke the method directly from the object, you don't need bind that same object.
In the wrapper function, you're directly invoking the method of the object (as in expression 2). Because you're invoking the method without "taking the method" (we "took" the methods into variables in the Fruit example), you don't need to use bind.
printButton.addEventListener('click', function(){
// directly invoke the function
// no method "taking" here
obj.printName();
});
Hope this helps :D
Note: You need to call printButton.addEventListener('click', obj.printName() ); without parenthesis in obj.printName() since you want to pass the function.
The answer lies in the way this is bound in Javascript. In JS, the way a function is called decides how this is bound. So when you provide the callback function like below:
printButton.addEventListener('click', function(){
obj.printName();
});
Notice, printName is being called via dot notation. This is called implicit binding rule when this is bound to an object before dot, in this case obj. Clearly in this case, you get the expected output.
However, when you call it like this:
printButton.addEventListener('click', obj.printName );
Notice that, all you are passing is the address of the function that is inside obj. So in this case info about obj is lost. In other words, the code that calls back the function doesn't have the info about obj that could have been used to set this. All it has is the address of the function to call.
Hope this helps!
EDIT:
Look at this crude implementation I call bind2 that mimics native bind. This is just to illustrate how native bind function returns a new function.
Function.prototype.bind2 = function (context) {
var callBackFunction = this;//Store the function to call later
return function () { //return a new function
callBackFunction.call(context);//Later when called, apply
//context, this is `obj` passed
//in bind2()
}
};
function hello() {
alert(this.name);
}
obj = {
name:'ABC'
};
var f = hello.bind2(obj);
f();
Notice: How function f() is hard bound here. f() has hard bound this with obj. You cannot change this to other than obj now. This is another thing with bind that probably will help you knowing.

When will an anonymous function be used?

For example below is an anonymous function that has been placed in parentheses so now the function can be stored as a variable and called on else where as seen in number 2, However how can script number 1 be called to run? How can it be identified if it has no name? And how to change an anonymous function to a defined function?
**Number 1**
(function() {
// Do something
})();
**Number 2**
(var funcName = function() {
// Do something
})();
funcName();
The first function is called immediately because it is followed by () which calls a function.
Then if you were to remove the () from around the var statement (which is an error):
The second function is also called immediately, for the same reason.
The value stored in funcName (which is called as if it were a function, so will cause an error if it is not a function) is the return value of the second function (and is defined by the code you represented as // Do something — the "something" needs to include "return a function").
How can it be identified if it has no name?
Names are only really useful for use in debuggers (where they are very useful in stack traces and the like). For identifying a function to call, you access them like any other object or primitive (via a variable, property, etc). A function declaration just creates a variable with a matching name in the current scope.
Yes, these are anonymous functions, but they are also functions that are being called / invoked immediately, and hence don't need names to be referred to later.
There are many uses for Immediately-Invoked Function Expression (IIFE), but one is to use functions to establish namespaces that do not pollute global

Using Variables as Parameter Names

Let's say I want to make a JavaScript function which sets variables to numbers, using the following format. It would not work, but why exactly? How could it be made to work?
function variableSet(varName, varValue) {
varName = varValue;
}
The idea is to create a variable with the name used as a parameter, and give it the value of the second parameter. How could this be done?
Not sure I understand your question. But if you need to give a variable name and it's value to overwrite the variable, it can be done like that:
this[varName]=varValue;
In this case "this" is your context, in which variable was defined. If you need to provide the other context, you can put it as other parameter, so function will look like this:
function variableSet(varName, varValue, context) {
context[varName]=varValue;

How do I pass a method through another method without it being called, and pass a variable object into it?

Sorry for my last question. This is the question with better formatting.
I have a method that I am passing a method through :
method("my_passed_method()")
function method(passed_method){
eval(passed_method.replace('()', + '(' + obj + ')' );
}
But this returns :
SyntaxError: missing ] after element list
I'm assuming this is just some simple JSON syntactical error.
I think you probably want this:
method(my_passed_method)
function method(passed_method){
passed_method(obj);
}
Note that when you're calling method, you're passing in a function reference, not a string, and you're not calling my_passed_method (there are no () after it), you're just referring to it.
Within method, you call the function via the variable passed_method, because that variable contains a function reference.
In JavaScript, functions are first class objects. Variables can refer to them, you can pass them around, etc.
Here's a complete, self-contained example:
// The function we'll pass in
function functionToPass(arg) {
display("functionToPass's arg is: " + arg);
}
// The function we pass it into
function functionReceivingIt(func) {
func("foo");
}
// Do it
functionReceivingIt(functionToPass);
Live copy | source
The name of a method, is at the same time, your reference to that method object. The parentheses, optionally with parameters in between them, make javascript call that method. This means your code can be rewritten to:
method(my_passed_method)
function method(passed_method){
passed_method();
}
So, what's going on here?
When you pass in the name my_passed_method, the javascript engine will look what that name maps to, and find that it maps to a functio object.
Than, inside the function call of method, that object is assigned to the parameter name `passed_method. Than, putting parentheses after this name will make javascript try to execute that object, which is indeed possible because this object is a function, and just like any other type, functions are what we call first class citezens. You can treat the just like any other value by assigning them to variables and passing them around.
In Javascript functions are considered objects. You may pass them as parameters to other functions, as demonstrated below.
function something(x){
alert(x);
}
function pass(func){
pass2(func);
}
function pass2(func){
func("hello");
}
pass(something); //alerts hello
Demo:
http://jsfiddle.net/wBvA2/
eval is evil; or so they say. You don't need to pass the function as a string you can just pass the function itself and then use Function.call or Function.apply to pass the argument (or just call it directly):
method(my_passed_method);
function method(passed_method) {
passed_method(obj);
// OR: passed_method.call(window,obj);
}
The circumstances where eval are necessary are very rare.
Note that your code will evaluate obj as javascript, so the outputs may differ.

In javascript functions, can you set this.function = function?

I have run into this jquery plugin and i quite understand how this works:
$.functionone = function(){
function setOptions(newOptions){
...
}
this.setOptions = setOptions;
}
What i dont understand is what does this actually do? this.setOptions = setOptions can you call a function without parenthesis? What is the relationship between this.setOptions and setOptions by itself?
Functions in JavaScript are objects like (nearly) everything else. When you do this:
this.setOptions = setOptions;
you're not calling the setOptions function, you're just assigning a reference to the function to a property, exactly like setting a property to any other object, like this:
var dt;
dt = new Date();
this.today = dt;
With functions, you'd do this so you can later call the function via the property (which sets up the this value to be the object the property's on, which is handy). It's a bit clearer what's going on if you use a different name for the property than for the function:
function functionName() { ... } // Declares the function
this.propertyName = functionName; // Sets the property
functionName(); // Calls the function (with `this` = the global object ["window", on browsers])
this.propertyName(); // Also calls the function (but with `this` = the object the property's on)
The pattern you identified, declaring a function and then separately setting a reference to it on an object, is frequently used to make sure the resulting function has a name. You can create a function and bind it to a property like this:
this.setOptions = function() {
...
};
...but then the function doesn't have a name (the property does, but not the function), which can be an issue when you're trying to debug because debuggers show you the names of functions in various contexts (call stacks, for instance). If a lot of your functions don't have names, even though the properties referring to them do, it makes debugging difficult. More about anonymous vs. named functions here. (There's also a difference in terms of when the function is instantiated, but going into it here would just complicate things.)
You'd think you could combine things, like this:
this.setOptions = function setOptions() { // <=== DON'T DO THIS
...
};
...but although that mostly works, it triggers a bug in Internet Explorer / JScript (it creates two different functions for that code, which is at best a memory waste and at worst a very subtle and time-wasting problem, as it was in this question).
The function setOptions is only called if you add parenthesis: setOptions(). If you do not add parenthesis, you have a reference to a function. This is just like a normal variable, only it contains a function reference instead of some other value.
If you set this.setOptions = setOptions, you make a function setOptions on the this object, which points to the same function as setOptions. That is, if you call it using this.setOptions(), the referenced function will be called.

Categories

Resources