When I reading this answer, find var g = f.call.bind(f);. I can't understand this with my first sight.
So does it has some direct meaning, and has some appropriate usage scenarios?
And further when you using call(or apply) or bind or both in chaining, what will happen? Is there some laws?
var g = f.call.bind(f);. I can't understand this with my first sight.
I assume you're familar with both the .call() and .bind() Function methods? Well, it binds the f.call method to the function f.
Notice that f.call is just Function.prototype.call, it doesn't matter that we access it as a property on f because we don't call it here.
So does it has some direct meaning?
It might become more obvious when we look at the ES6 equivalent:
(Function.prototype.call).bind(f) // or
(f.call).bind(f) // is basically
(...args) => f.call(...args) // or more clear
(ctx, ...args) => f.call(ctx, ...args)
Does it have some appropriate usage scenarios?
Well, now that you know what it does, yes. It can take a prototype method and transforms it to a static function that takes the instance as the first argument. An example:
function Example(n) { this.name = n; }
Example.prototype.display = function() { console.log(this.name); }
Example.display = Function.call.bind(Example.prototype.display);
var e = new Example;
e.display(); // is the same as
Example.display(e);
Are there any laws for further chaining call/apply/bind?
Yes: as always, only the last property in the chain is actually called as a method. In the above example, theres no difference between f.call.bind(…), Function.prototype.call.bind(…) or Function.call.apply.bind.call.bind(…) - it always calls bind on call.
However, by passing them as arguments to each other, you can do some crazy things which are more or less useful.
Good question. Let's start off by considering an example that's come up on StackOverflow before: mapping all the strings in an array to lowercase. Of course I can write
strings . map(function(string) { return string.toLowerCase(); })
but that seems a bit verbose. I'd rather write
strings . map(CALL_LOWERCASE_WITH_ELT_AS_THIS)
So I might try
strings . map(String.prototype.toLowerCase)
or, to use the shorter idiom some prefer
strings . map(''.toLowerCase)
because ''.toLowerCase is exactly equal to String.prototype.toLowerCase.
But this won't work, of course, because map passes each element to the specified function as its first argument, not as its this. Therefore, we need somehow to specify a function whose first argument is used to call some other function as its this. That, of course, is exactly what Function.call does:
function.call(context)
The first argument to call ("context") is used as the this when calling function.
So, problem solved? We ought to be able to just say:
strings . map(''.toLowerCase.call)
and people have tried this and then wonder why it didn't work. The reason is that even though we are passing call of toLowerCase as the callback to map, map still has no idea that the callback is supposed to be called with a this of ''.toLowerCase. We need to explicitly tell map which this to use to call the function, which in the case of map we can do with its second "context" argument:
strings . map(''.toLowerCase.call, ''.toLowerCase)
Actually, since call is the same on any function object, we can simplify this to just
strings . map(Function.call, ''.toLowerCase)
This works and gets the job done beautifully.
However, whereas map provides this second "context" argument to specify the this to call the callback with, that is not something we can depend on being available in all situations. We need a more general way to say "make a function which calls Function.call with some particular function as this".
That is exactly what bind does. It says "take a function and make another function which calls it with a particular this":
function.bind(context)
In our case, what we want to do is to "take the function Function.call and make another function which calls it with a this of ''.toLowerCase. That is simply
Function.call.bind(''.toLowerCase)
Now we can pass this to map without having to use the second argument:
strings . map(Function.call.bind(''.toLowerCase))
That works exactly the same as strings . map(Function.call, ''.toLowerCase), because in general map(fn, ctxt) is precisely equal to map(fn.bind(ctxt)).
The following breaks this down into a readable form, step by step:
Function . // From the Function object
call . // take the `call` method
bind( // and make a new function which calls it with a 'this' of
''.toLowerCase // `toLowerCase`
)
When this construct is specified as a callback, such as to map, it means:
Invoke call with the first argument passed in and ''.toLowerCase as this, which by virtue of the definition of call, means to call toLowerCase with that argument as this.
Some people prefer to simplify this a bit by saying
var call = Function.call;
var toLowerCase = ''.toLowerCase;
strings . map(call.bind(toLowerCase))
or, using the second argument provided by map, just
strings . map(call, toLowerCase)
which is almost readable as English: "map each string to the result of calling toLowerCase.
Another common, related use case would be specifying the callback in a then on a promise. Consider the following code:
promise . then(function(result) { result.frombulate(); })
That's fine, but it's a bit verbose. And then has no way to pass in a context to be used as this when invoking the success or failure handler. But with the above, we can now write:
promise . then(call.bind(frombulate))
There are other use cases for the call.bind idiom, but this is one of the most common ones: define a callback whose effect is to invoke some function with the parameter passed to the callback as its this.
With ES6 fat arrow functions, of course, I can write
promise . then(result => result.frombulate())
so there is relatively less advantage in the shorthand offered by call.bind(frombulate), and it is hard to deny that the fat-arrow version is more readable than that using bind.
The following question might be of interest too: Array.map and lifted functions in Javascript.
m.call.bind(m)
can be used as shorthand for:
function(x){return m.bind(x)()}
The former is the "point-free" form of the latter,
arguments are implicit. It would be useful with
list-operations like map(), making them shorter.
You can write stuff like:
let m = "".toUpperCase;
let fun = m.call.bind(m);
let see = ['a','b'].map(fun);
Related
I was looking through the React source and stumbled across a requirement with var emptyFunction = require('fbjs/lib/emptyFunction');.
I looked at this function and was confused by what it does.
Here is the function
function makeEmptyFunction<T>(arg: T): (...args: Array<any>) => T {
return function() {
return arg;
};
}
const emptyFunction: (...args: Array<any>) => void = function() {};
In the comments, they give the following explanation which I was confused by:
This function accepts and discards inputs; it has no side effects.
This is primarily useful idiomatically for overridable function
endpoints which always need to be callable, since JS lacks a null-call
idiom ala Cocoa
I have never come across null call idiom and was hoping someone could clarify what this means and explain the purpose of this function in less technical language.
Hopefully this question will not get looked down on because it isn't exactly code related. Maybe it belongs somewhere else, if so I'm sorry.
When programming in JavaScript, we can take a function as a parameter to a certain operation. As an example, a function may have a callback which is invoked after some kind of event.
function doIt(callback) {
// some work
callback();
// more work
}
Now if this callback is an optional parameter and it's not provided, we will get Uncaught TypeError: callback is not a function error because callback is undefined. There are two solutions to this issue. The obvious one is checking the callback with an if statement. Another option is set an empty function as the default value of callback if it's not assigned. This approach is very useful and shines if we have multiple places which invoke the callback function. So we don't need to check it for undefined every time before calling it.
function doIt(callback) {
callback = callback || function(){};
// some work
callback();
// more work
}
Likewise, there are lots of use cases where we can have overridable functions variables. It's a common pattern to set these type of variables to empty function as the default value so that we can call them without worrying about whether those are assigned/overridden or not.
Also, in some special cases, it's useful to have functions which do nothing but return a particular value. makeEmptyFunction is used for creating such functions. Basically, it returns a function which does nothing but returns what ever the parameter pass to it.
emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
As you can see in the file, above code generate an empty function which returns false value.
"null call idiom" is something we find in Objective-C/Cocoa programming. It basically allows you to call a method of an uninitialized object (null pointer) without giving any errors like in most of the other languages. I think that's what the author have tried to explain in the comment.
Since JavaScript doesn't have such language feature, we explicitly achieve it using empty functions. Some people call it no-op or noop and you can find similar helpers in other popular JavaScript libraries such as JQuery and AngularJS also.
I saw the following line in a node js code base.
_ => { return resolve(abc);}
Can any one give me some hint on what this _ means?
I know => is fat arrow function. This line is from a snippet of promise.
At the coaxing of a discussion elsewhere in this question, I'll turn my comments into an answer.
First off, I assume you aren't asking about arrow functions in general, but are just curious about the _ in your code sample.
There is a convention (used by some) to declare and name a parameter to a callback function that you know is passed, but you are not going to be using with an underscore as a sort of placeholder. It's a signal to people reading the code that there is an argument being passed to this callback, but you don't plan on using it in this particular invocation. It's presence is not functional, but more for
Now, without knowing what was in the head of the developer who wrote the line of code you asked about, we can't know for sure what the underscore means, but it does appear to match that previously described convention. There is one argument to the callback and it is not used in the implementation of the callback.
So, if our guess that this is a use of that convention is true, then in the arrow function that you show:
_ => { return resolve(abc);}
It is likely expecting one argument, but this particular use of that callback does not plan on using it, thus they named it with an _ just to signal that.
Now, there is no particular reason in Javascript that the callback needs to even define a single argument like this that be used. The callback could just as well have been defined as:
() => { return resolve(abc);}
since there's no requirement in Javascript that you declare arguments you aren't going to use.
If the callback took two arguments and it was the first one that you weren't going to use, then it does have to be declared as something in order to allow access to the second argument:
(_, secondArg) => { return resolve(secondArg);}
It means that the arrow function argument is not used. They use _ as argument name for the arrow function.
Doesn't this mean something like this?
function(_){
return resolve(abc);
}
What's happening here is that the code is using (some of) the concise syntax for arrow functions. To do this you'd write a function like this:
var f = x => x*x;
according to the docs
So with your example, the argument x is named with an _ (a valid character for variable names):
var f = _ => {return resolve(abc)}
But, it doesn't need the return or the brackets, either. It could be just:
_ => resolve(abc);
Perhaps a more readable way to write it would be with the parathesis:
() => resolve(abc);
I'm trying to understand how to read the code below (taken from MDN's article on Array.prototype.slice) to understand what happens when it runs.
function list() {
return Array.prototype.slice.call(arguments);
}
My understanding is that the return statement gets a reference to the Array.protoype.slice method. This leads to my first question, "if this is a reference to the slice method, why doesn't it need to be invoked, e.g. Array.prototype.slice().call(arguments)?"
Assuming that this is a call to the slice method, and since there is no argument being immediately passed into it, my second question is "is JS 'seeing' the call method chained to slice and then trying to resolve a value to pass to slice from the call(arguments) method?"
If this is the case, is this method chaining and is this how JS performs chaining operations: from left to right and when there is no argument explicity passed to a method, it tries to resolve a value from a subsequent method to return implicitily to the "empty" callee on the left?
Thanks.
Why doesn't it need to be invoked? — because, as you say, it's a reference, and that's all that's desired. The code wants a reference to the function, not a result returned from calling the function.
Is JS 'seeing' the call method chained to slice and then trying to resolve a value to pass to slice from the call(arguments) method? — well I'm not sure what that means. The reference to the .slice() function is used to get access to the .call() method (inherited from the Function prototype). That function (slice.call) is invoked and passed the arguments object as its first parameter. The result is that slice will be invoked as if it were called like arguments.slice() — which is not possible directly, as the .slice() function isn't available that way.
Overall, what the code is doing is "borrowing" the .slice() method from the Array prototype and using it as if the arguments object were an array.
Sometimes you'll see that written like this:
return [].slice.call(arguments);
It's a little shorter, and it does the same thing (at the expense of the creation of an otherwise unused array instance).
call in javascript is a way of invoking a method within the function, which hard binds the context of this within a function to the parameter passed to it..For more detail regarding callgo through the link below
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
If you want to know more about this and why call is being used, I highly recommend you to go through this github repo:
https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/ch1.md
Secondly, by default every regular function expression in JS has an arguments object, which is an iterable which is nothing but the list of parameters passed to that function.
function foo()
{
console.log(arguments); //1,2
}
foo(1,2)
More about arguments
https://www.google.co.in/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=arguments%20in%20javascript
And if you want to learn JS properly, blindly go through this repo:
https://github.com/getify/You-Dont-Know-JS
Have a look at the docs for Function.prototype.call():
The call() method calls a function with a given this value and arguments provided individually.
Since .call is a part of Function.prototype, every function has it as a property, including Array.prototype.slice (or [].slice).
According to the docs for Array.prototype.slice:
If begin is undefined, slice begins from index 0. If end is omitted, slice extracts through the end of the sequence (arr.length).
It's getting a reference to the Array.prototype.slice property (function) and running its .call function. The 1st parameter to call is the context (or this value) and any other parameters are passed to the chained method. .slice() doesn't require any parameters and without any it just returns the elements as an array.
So, what's happening is that it's taking arguments - which is not actually an array, just an "array-like" object (with numeric properties and a .length property) - and running .slice() on it like it was an array. This makes it r"convert" arguments into an array.
This doesn't work:
var s = '^foo';
console.log(['boot', 'foot'].some(s.match));
Uncaught TypeError: String.prototype.match called on null or undefined
But this does:
var s = '^foo';
console.log(['boot', 'foot'].some(function(i) { return i.match(s) }));
Why is this? I imagine somehow the String.prototype.match function is too "primitive" or something, but why exactly? Since I'm not using ES2015, the second version seems quite verbose. Is there an alternative?
EDIT
When I wrote the above, I actually got it backwards compared to my actual need, which was matching one string against a number of regexes. But thanks to the great answers and comments below, I get it: [/^foo/, /^boo/].some(''.match, 'boot').
Note: The value of this is determined by how the function is called! (exception: bound and arrow functions)
If you pass s.match to .some, then the function will be called with this set to the global object (e.g. window) not the string it "belongs" to.
I.e. it would be equivalent to this:
String.prototype.match.call(window, 'foo')
This cannot work because this has to refer to a string object.
You could solve this by binding the function to a specific this value:
['boot', 'foot'].some(s.match.bind(s));
Learn more about this:
MDN - this
You Don't Know JS: this or That?
How to access the correct `this` context inside a callback?
A function value in Javascript does not bring its object along with it. The value of s.match is a plain function value, with no knowledge that you happened to find it attached to s. In fact, no matter what String you access it through, it's always the same function value:
"foo".match === "bar".match
//= true
When you call a function through an object, Javascript sets this to that object for the duration of the function call. But as soon as anything comes between retrieving the function value and calling it, any object association is lost.
You can create a function that does remember a specific this value using bind, as in #Felix King's answer. someFunction.bind(someObject) has approximately the same meaning as function(arg1, arg2,...) { return someObject.someFunction(arg1, arg2,...); }, but it automatically handles the number of parameters properly.
This a theoretical question:
Is there a generic name to refer to all those jQuery functions that don't accept functions as a parameter?
Such the index(), children(), height() ...
UPDATE:
If i know the name then I could make a question like this: "Can I pass a function to a "named" function?"
To give a little more detail, I have tried to pass a function as a parameter to jQuery's .index() method but it does not work:
textbox.closest('tr').index(function(){var index = $(this);});
All jQuery functions that take parameters can take functions. In JavaScript, functions are objects, and neither jQuery or vanilla JavaScript are type-safe. In other words, as long as the function accepts parameters, it will accept a function as one of its arguments.
Ergo, methods that do not accept any parameters are the only methods that will not accept functions.
EDIT:
If you want to get technical, then even methods that do not accept any parameters will still accept a function as an argument. Just as JavaScript isn't type-safe, it also doesn't actually enforce any rules regarding the function's signature, i.e. it doesn't check that the number of arguments entered matches the number of arguments defined. This is why you get a "null reference" error (if unhandled) instead of a "no function [function name] takes the arguments [arguments list]". This is also why you can pass an unlimited number of arguments to a function, even if it only takes one, two, or none.
UPDATE:
With regards to my solution to your original question, I would like to clarify by adding that jQuery is a solid language in that it often will simply return null when it is passed invalid arguments (but it will not error out when being passed an incorrect number of arguments). JavaScript is the same in many situations, but, as I implied and common sense would dictate, it would be nonsensical to pass too many or too few arguments to a method, regardless of legality.
With regards to your updates and your comments, I think that you're misunderstanding the fundamental use of jQuery's .index() method. When used properly, this method is called on a collection of elements and has a selector (or an element to match) as a parameter, and returns the index of the first occurrence of an element that satisfies the given selector, or matches the given element.
Update:
From your updated example, I can see that I was correct in thinking that you are misunderstanding the use of the .index() function a little bit. The function takes either a selector or an element, but you passed a function that doesn't return either. Here is what you would need (using your existing syntax):
textbox.closest('tr').index(function(){ return $(this);});
OR (more simply):
textbox.closest('tr').index($(this));
To add a bit more detail (and, perhaps, better answer your initial question), you could also do something like this:
function getOnlyParagraphElements() {
return this.tagName === "p";
}
var collection = $("body").find("*");
var firstParaIndex = collection.index(getOnlyParagraphElements);
This was only an example (and yes, I know that I could just use jQuery to get paragraphs), but the concept is the same - this is how you make your own selector.
Also note that in your examples, you are always checking against a one-item collection, meaning you will only get either the value 0 or the value -1 (if the element doesn't match the selector/passed in element). If your goal is to get the index of the element that you are calling the method on relative to its siblings, then you need only call the method without supplying any parameters.