Recently I had asked a question
Extract & call JavaScript function defined in the onclick HTML attribute of an element(using jQuery attr/prop)
I needed to programmatically access the onclick attrib of a button which had a function call along with param's in it then supply an extra param & make a function call(onclick=doSomething(2,4)).
But as I figure out that the use of apply/call can also come handy to supply extra param's.For this I extracted the the function name from the attribute & it comes in a string like
arr[1] = 'doSomething';
I tried using Function Constructor to treat this as a function but it doesn't work
(like Function(arr[1])) Why?
Solution mentioned Javascript: interpret string as object reference? works fine. But why it cant be achieved via the function constructor?
Some code info
var funDef ='doSomething'; // this is the name of real function defined in the script
var funcName = new Function(funDef); //expected it to return reference of function doSomething,shows function anonymous() in console
var funcArgs = [5,7,10];
funcName.apply('',funcArgs); //this is the function call.
In this case function does not get called untill I replace
var funcName = new Function(funDef); with var funcName = eval(funDef);
Thanks.
new Function and eval are not interchangeable. When you eval, you are creating code that runs immediately. When you create a Function, that is going to return a function that you can run yourself.
It's almost as if you do:
// This executes 1+2
var resultOfEval = eval('1+2');
// This creates a function that when called, returns 1+2
var resultOfWrappedEval = eval( '(function(){return 1+ 2})' );
// This is much like the line above, you have to call it for it to execute
var resultOfFunctionCtor = new Function('return 1+ 2;');
console.log('resultOfEval', resultOfEval);
console.log('resultOfWrappedEval', resultOfWrappedEval);
console.log('executing resultOfWrappedEval', resultOfWrappedEval());
console.log('resultOfFunctionCtor', resultOfFunctionCtor);
console.log('executing resultOfWrappedEval', resultOfFunctionCtor());
If you show more of your code, we can suggest something, but the key is that when calling the Function constructor, the code doesn't run immediately, it returns a reference to the newly created function.
Also, you seem to understand that you can call the function yourself. What is the problem with doing that?
I discussed this on the JavaScript chat room from where I understood that new Function(..) constructor needs whole function body to return reference in the way I was expecting.
The function constructor does not consider the definition of the doSomething function that is written in the script while eval does.
Other ways that could be fit in this scenarios are here:
Javascript use variable as object name
Comments?
Related
I'm trying to put a member function from a specific object in a standalone variable, hoping to be able to call the function (on the original object) by simply using the new variable.
So something like this:
var str = "abcdefgh";
var fn = str.indexOf;
console.log(fn("e")); // supposed to output 4
So fn(x) is supposed to do the same as str.indexOf(x). But this doesn't work. Is there another way I can pull this off?
Note that the difficulty here is I want fn to call the function on that specific str object.
So fn is to become some sort of closure.
From the You Don't Know JS Series, JS determines the this in this way
Is the function called with new (new binding)? If so, this is the
newly constructed object.
var bar = new foo()
Is the function called with call or apply (explicit binding), even
hidden inside a bind hard binding? If so, this is the explicitly
specified object.
var bar = foo.call( obj2 )
Is the function called with a context (implicit binding), otherwise
known as an owning or containing object? If so, this is that context
object.
var bar = obj1.foo()
Otherwise, default the this (default binding). If in strict mode,
pick undefined, otherwise pick the global object.
var bar = foo()
Your problem
When you call the indexOf on the str.indexOf('e'), JS engine starts to lookup for the context in the function. It sees that you have called the function with . notation on a string object and refers the context to it. But
when you get the reference of the function and tries to call like fn, engine starts to search the context (mentioned above) and didn't find anything. Otherwise when you get a function reference outside it loses it's context. So you need to give the context explicitly.
Here I write, that whenever the fn will be called, the this inside the function will refer to the str variable.
var str = "abcdefgh";
var fn = str.indexOf.bind(str);
console.log(fn("e")); // supposed to output 4
If you are using ES6 variety javascript, you can use an "arrow function" to achieve this. It's a nice, short syntax.
var fn = () => str.indexOf("e");
For further reference,
see the mozilla docs on arrow functions
This variable can of course be passed around. Note that with this solution, the variable fn holds a direct reference to the string that you are executing a function on, so it solves your context problem.
Can someone please explain why we can simply pass a method name to a higher order function and everything works just fine. I know in something like Java I have to call the method words on each element individually. I was told that in Javascript if method signature matches we can simply pass in the name of the function with () and it will work. It is great but I want to know whats going on in the background. Why are we able to do this in javascript ?
function words(str) {
return str.split(" ");
}
var sentences = function(newArr){
return newArr.map(words);
}
In many languages you can pass a reference to a function as an argument to a function. That then allows the host function to use that argument and call that function when appropriate. That's all that is going on in Javascript. When you pass the name of a function without the () after it, you're just passing a reference to the function. That enables the host function to use that function as an argument and call it some time later.
In your specific example, .map() expects you to pass in a function that it will call once for each item in an array. So, you pass the name of a function that will then get called multiple times, once for each item in the array. That function you pass has a bit of a contract that it has to meet. It will be passed three arguments (value, index, array) and it must return a value that will be used to construct a new array.
In Javascript, since there is no argument type checking by the language, it is the developer's responsibility to make sure the arguments of the function you are passing match what the caller of that function will actually pass to it and you have to consult documentation of the calling code itself to know what arguments will be passed to it. You can name the arguments anything you want (that is entirely internal to your function implementation), but the order and the quantity of the arguments is determined by the caller and you must declare your function to match what the caller will provide.
Once thing that confused many in Javascript.
If you pass just a function name, you are passing a reference to the function (something that the host function can call at some later time).
array.map(myFn) // passes a function reference
Or, use an inline function (same outcome):
array.map(function(value, index, arr) {
// code goes here
})
If you put parens at the end of the function name, then the function is executed immediately and the return value of that function execution is what is passed:
array.push(myFn()); // pushes the result of calling myFn()
You are calling the words function repeatedly. You're calling it for each iteration of the map function.
The map function takes a callback which it runs for every iteration. That callback is usually in the form of
function (elementOfNewArr, indexOfNewArr, newArr) { }
Because functions are objects, you can store them on a variable and use that new variable name to call that function, instead of its original one. That's mostly the use of functions as objects. You can toss them around.
let foo = function () { return 'jasper!'; }
let boo = foo;
let ron = boo; // ron() will now return 'jasper!'
So, what you've done is plop in your callback function, though it was defined elsewhere. Since callback functions, like all functions are objects, you can declare that callback function, "saving" it to whatever variable you want and use it in anywhere that you can use it normally.
This is super useful if you have to use the same function in more than one place.
What I believe you are misunderstanding is that functions themselves can be treated the same as other variables in javascript. Consider this example:
var newArr = [1,2,3,4];
newArr.map(function(item){
return item * item;
});
In the above example, a function is passed as an argument to the map() function. Notice that it is described anonymously (no function name given). You can accomplish the exact same thing like this:
var newArr = [1,2,3,4];
function squared(item){
return item * item;
}
newArr.map(squared);
These two examples achieve the same thing, except in the second example, rather than writing the function in place, we define it earlier in the code. If it helps, you can even create the function in the same way as you would any other regular variable:
var squared = function(item){
return item * item;
};
You can pass this function around the same way. If you want to know the difference between defining functions in these ways try var functionName = function() {} vs function functionName() {}
I had a question when reading a source code. The code example is as below:
// ... some code omitted
function p() {var u=new i();this. $Arbiter0=new s(); this.$Arbiter3=[];}
p.prototype.subscribe = function() { ... }
p.call(p) // <-- what is the purpose of this statement?
I'm new at JavaScript. I read from textbook that, when you use Function.call(Function), it usually means borrow inganother function constructor, in order to do some code-reuse/inherit stuff. BUT, I'm not sure what the purpose of doing it in this code example, i mean, the function is calling the function itself?
Clarify:
I know the use of Function.call(). I just want to know, what is the benefit of doing foobar.call(foobar)?
====
The complete source code is as below:
https://fbstatic-a.akamaihd.net/rsrc.php/v2/y6/r/USEL5meM70H.js
Search 'p.call(p)' in that source code. There is only one occurrence in that file.
====
Thank you.
p.call(p) has the effect of calling the function p, such that the value of this, within the function body, is the function itself.
This allows you to add properties to the function from within the function.
Relevant documentation for Function.call can be found here.
Since this is minified code, it's possible that this construct is an artifact of the minification process. It seems that the intent here is to initialize p; it's probably setting up data structures for storing subscribers.
The first argument for the .call is the element that will be used as this in the executed function.
See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
You know in JavaScript, functions are also Objects. That means you can have method and properties associated to functions.
For example :
I can create a function called foo and add a property to it like below
function Foo(){};
Foo.bar = [1,2,3,4,5];
Foo.sayName = function(){ alert("hi Tom")};
This methods are called as static methods ( Classical OOP pattern: function constructor act like a class in javascript ), so that you don't need to instantiate an Object of Foo to access sayName method.
Coming back to the actual question. What happens when you do Foo.call(Foo);
The call method expect an object as the first parameter, and invoke the function on which it's called. When the function is invoked, this pointer will be pointed to the object passed. In this case, it's the Foo function ( Object ) itself.
Assume that if Foo function is written this way
function Foo(){
this.bar = [1,2,3,4,5];
this.sayName = function(){ alert("hi")};
}
After executing Foo.call(Foo), you can see that the actual Foo function ( Object ) will have the properties bar and method sayName got added.
I guess the script which you have sent is doing that to reduce code duplication.
I've just come across this little snippet of JavaScript code online:
exampleSocket.onopen = function(event) { // rest of code here;}
And I'm rather confused about the function(event) part, as there are no comments for me to analyze. (Who needs comments when you're designing bi-directional duplex connections? Haha ).
What exactly is function(event)? I always thought you had to define a function name with the function in javaScript. Is this an example of bad code? Additionally, the (argument-parameter-whatever) 'event' isn't even defined anywhere else in the code. Just bam. There it is. Is it necessary to define that, or is (event) a special predefined value? Lastly, if you were to replace (event) with some other value like (e), would the code still work?
Thanks
What you've got there is a function expression, not a function statement.
In a function statement, the name is mandatory. In a function expression it is optional. A function expression with a name is called a named function expression. A function expression without is called an anonymous function
There are a number of subtle differences between all these different methods of declaring a function which are covered in this question; var functionName = function() {} vs function functionName() {}
What you're doing here is setting the onopen property of exampleSocket to a function (expression). Note that you are not running that function at all; you are simply declaring it, and saving a reference to it in exampleSocket.onopen.
This means that someone can execute that function when they want to by calling;
exampleSocket.open();
They can pass a parameter to the function, which you can use inside the function using the event variable (and to answer your question; event is not a special word. You can call it anything).
exampleSocket.onopen = function (event) {
console.log(event); // will log "hello"
};
exampleSocket.open("hello");
The fact the variable event isn't used anywhere will likely mean the developer has named the argument to say "hey, look, you can use this if you want to", but hasn't in his actual implementation.
You don't have to declare the variable yourself. It is declared already by being named in the argument list, and it will be initialized to a value when someone passes an argument when they call the function.
Note that we could define this event handler using a function statement;
function foo(event) {
console.log(event);
}
exampleSocket.open = foo;
... or via a named function expression:
exampleSocket.open = function foo(event) {
console.log(event);
};
To confuse things (don't worry about this; it's a quirk of JavaScript) the name of a named function expression is only available inside the function itself;
exampleSocket.open = function foo(event) {
console.log(event);
console.log(typeof foo); // you'll get "function"
};
console.log(typeof foo); // you'll get "undefined"
... but in a function statement, you'll be able to access the name both inside and out.
I hope this helps... it's a bit of a "brain dump" of information :).
This is an anonymous function. A function is a value, and you can declare and store functions like this. More information on that syntax in this question.
Reading the code (I don't think it needs any more comments than it already has), you are writing a handler function which is called when the socket opens. The socket open event will be passed to the function in the variable event.
Why event? Because the API, whatever it is, expects to pass in an argument that represents the 'open' event.
It's a simple and common JS event-binding function.
It attach an anonymous function to the "open" event of "exampleSocket".
When such event is fired the declared function is called.
Each event may have some parameters, which contain additional info about the event itself.
You can name that parameter the way you want ("event","e" or "anythingElse") and then you can refer to it in the anonymous function body.
You are basically assigning a function value to exampleSocket.onopen, which can then be called elsewhere. Imagine something like this:
var obj = {};
obj.onsomething = function(a, b, c, d) {
alert(a+b+c+d);
};
obj.onsomething(1, 2, 3, 4);
In this case, I gave obj.onsomething a function that takes 4 parameters (should be numbers) and alerts the sum. Then I can just call obj.onsomething with 4 parameters.
So the function that you assign to exampleSocket.onopen will get called when it is appropriate (for example, when the socket is open).
Hope that helps.
I have been writing javascript for one or two months , I never used Function keyword , like Function.method(); when I define function , I simply define it as :
function fooBar () {};
Can you give me an example when using Function is more convenient ?
You shouldn't use the Function constructor so often, it basically uses code evaluation to build a function.
It requires string arguments, being the last argument the function body, and the previous ones will be the arguments of the new function itself, for example:
var add = new Function("a", "b", "return a + b;");
add(5,5) == 10;
When you should use it?
As I said not so often, I personally try to avoid them since they use code evaluation.
A thing to note is that no closures are created when functions are built in this way, which can be a good thing for some performance circumstances, for example to shorten the process of identifier resolution, but you should use them with care...
Every function in JavaScript is
actually a Function object.
Read Function
Function objects created with the
Function constructor are parsed when
the function is created. This is less
efficient than declaring a function
and calling it within your code,
because functions declared with the
function statement are parsed with the
rest of the code.
function view(){
document.getElementById('one').innerHTML="New Text here";
}
this function can you call from either keyboard events of mouse events