I came across this excerpt while reading Chapter 2 of "You Don't Know JS Yet".
But beware, it's more complicated than you'll assume. For example, how might you determine if two function references are "structurally equivalent"? Even stringifying to compare their source code text wouldn't take into account things like closure.
I just want to make sure if I understand correctly on what the author meant by "closure". I'm thinking of this example:
function x() {
console.log('Hello');
}
const foo = x;
function y() {
const bar = x;
if(foo.toString() === bar.toString()) { // returns true but the closure of foo and bar is different
// do something
}
}
Also, under what circumstances we need to compare two functions? Thanks.
Here is an example of two functions that look the same yet will behave differently because of their closure:
const what="great",
fun1=()=>console.log(`This is ${what}!`);
{ // this block will have its own closure
const what="stupid",
fun2=()=>console.log(`This is ${what}!`);
console.log(fun1.toString()==fun2.toString());
fun1();
fun2();
}
The author means that closure is the data that a function carries with it, including the variables from its surrounding scope that are used in its body. In the example you gave, even though the two functions foo and bar have the same source code (as indicated by the toString() comparison), they are not structurally equivalent because they have different closure values.
As for when to compare two functions, you might need to compare two functions in certain scenarios, such as when you want to determine if two functions have the same behavior, if they have the same closure, or if they are bound to the same execution context.
As far as I can tell, the author is saying "closure" as a reference to scope. I think you are correct.
As for the comparison of two functions, the most obvious case that comes to mind is comparing the time and space complexity performance of two functions that perform the same overall task. However, in regards to the authors 'structurally equivalent' notion, I don't know.
Related
I'm fine with the pure function concept on pretty simple examples like...
function addTwo(val){
return val + 2;
}
Given the same arguments, it yields the same result, leading to Referential Transparency and good deterministic code.
But then I've came across examples like these (taken from professor frisby mostly adequate guide, but I've found similar examples on other FP JS books)
//pure
var signUp = function(Db, Email, attrs) {
return function() {
var user = saveUser(Db, attrs);
welcomeUser(Email, user);
};
};
var saveUser = function(Db, attrs) {
...
};
var welcomeUser = function(Email, user) {
...
};
and I don't get why isn't considered an external dependency (so, impure) the call to saveUser or welcomeUser.
I know that from a function/IO point of view, signUp always return the "same" (an equivalent) wired function, but it feels weird to me.
It's difficult to me to understand why even
function multiplyBy(times){
return value => value * times;
}
const fiveTimes = multiplyBy(5);
fiveTimes(10);
is considered pure. From the returned function POV, accesing to times is a lookup on the scope-chain, it could come from the immediate outer scope, or from beyond (like global scope).
Any one wants to bring some light to this?
My explanation for function purity in JavaScript is that there's no such thing as a binary "pure" or "impure", but rather a spectrum of confidence that a function will behave predictably. There's all kinds of tricks that can be played to make a function that seems pure not be, by passing an object with a side-effect getter on it, for example.
So, once we realize that purity is about degree of confidence, we can then ask, how confident am I that some function will behave the way I expect? If that function references another function, how sure are you that the other function is pure? And, moreover, how sure are you that the identifier that's referencing that other function doesn't / can't get re-assigned to point to some other function you aren't aware of?
I personally code my programs so that I almost never re-define an identifier that's pointing at a function, especially if that function is declared rather than just a function expression. In that way, I feel very confident (say, 99.99%) that if foo(..) calls bar(..), and I'm confident that bar(..) is reliably pure, then foo(..) is also reliably pure, because I know I won't reassign bar(..) to any other function and cause surprising results.
Some people even go so far as to define their function identifiers with const fn = function ... I don't think that helps all that much... it probably would take my confidence level from 99.99% to 99.999%. That doesn't move the needle enough to justify its usage, IMO.
Moreover, on the closure part of your question: if an inner function closes over an outer variable that's still contained in a pure function, and nothing re-assigns that variable, then it's effectively a constant, so my level of confidence is very high in the predictability.
But again, the take away is that function purity in JS is about level of confidence, not an absolute binary yes or no.
The definition of a pure function is:
A function that does always evaluates the same result value given the same argument value(s) and that does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.
"Having dependencies" plays absolutely no role in defining a pure function. The only thing that matters is whether the function has any side effects and whether its result depends on external state. If a function behaves exactly the same and always produces the same result given the same input, it is pure. If a function has any side effects (modifies global state) or behaves differently depending on external state, it is impure. A function may have a dependency on (read: call) another function as part of its operation; as long as that other function is also pure, that doesn't taint the purity.
The signUp example you show is pure, because it only acts on its input and always returns the exact same output when called with the same input. Note that the function itself doesn't "do" anything. It's not calling the database or produce any side effect. All it does is return a function. But this returned function is always the same if the input is the same. That returned function is in effect impure; but the function that produced it is not.
I recently joined a large software developing project which uses mainly JavaScript and a particular question has been on my mind since day one. I know this issue has been here on SO before, but I have never seen the core question being properly answered. So here I ask it again:
Are there any benefits in JavaScript in using function expressions rather than function declarations?
In other words, is this:
var myFunction = function () {
// Nice code.
}
in any way better than this:
function myFunction () {
// Nice code.
}
As I see it, function expressions only introduce negative aspects on several levels to the code base. Here I list a few.
Function expression as the one above, suddenly forces you to be careful with forward references, as the anonymous function object that the myFunction variable refers to, does not exist until the variable expression actually executes. This is never a problem if you use function declarations.
Apart from generating twice as many objects as in the case with function declarations, this usage introduces a very bad programming habit, which is that developers tend to declare their functions only when they feel they need them. The result is code that mixes object declarations, function expressions and logic in something that obscures the core logic of a piece of code.
As a side effect of 2), code becomes much harder to read. If you would use proper function declarations and only var declarations for objects that actually will be variable in the code, it becomes far easier to scan the indentation line of code segment and quickly find the objects and the functions. When everything is declared as "var", you are suddenly forced to read much more carefully to find this piece of information.
As yet another nasty side effect of 2), as users get into the bad habit of only declaring their functions when they feel they need them, function expressions start showing up inside event handlers and loops, effectively creating a new copy of the function object either each time an event handler is called or for each turn in the loop. Needless to say, this is bad! Here is an example to show what I mean:
var myList = ['A', 'B', 'C'];
myList.forEach(function (element) {
// This is the problem I see.
var myInnerFunction = function () {
// Code that does something with element.
};
};
So to sum up, at least in my view, the only situation in which it is fair to use something like:
var myFunction = function () {
// Nice code.
}
is when your logic intends to change the myFunction reference to point at different functions during execution. In that situation myFunction (the variable) is something that is variable in the code, hence you are properly informing a different programmer of your intents, rather than confusing him/her.
With this background in mind, I ask my question again. Have I missed something central about function expressions (in the context described above) in which they provide any benefit over function declarations?
Are there any limits to what types of values can be set using const in JavaScript, and in particular, functions? Is this valid? Granted it does work, but is it considered bad practice for any reason?
const doSomething = () => {
...
}
Should all functions be defined this way in ES6? It does not seem like this has caught on, if so.
There's no problem with what you've done, but you must remember the difference between function declarations and function expressions.
A function declaration, that is:
function doSomething () {}
Is hoisted entirely to the top of the scope (and like let and const they are block scoped as well).
This means that the following will work:
doSomething() // works!
function doSomething() {}
A function expression, that is:
[const | let | var] = function () {} (or () =>
Is the creation of an anonymous function (function () {}) and the creation of a variable, and then the assignment of that anonymous function to that variable.
So the usual rules around variable hoisting within a scope -- block-scoped variables (let and const) do not hoist as undefined to the top of their block scope.
This means:
if (true) {
doSomething() // will fail
const doSomething = function () {}
}
Will fail since doSomething is not defined. (It will throw a ReferenceError)
If you switch to using var you get your hoisting of the variable, but it will be initialized to undefined so that block of code above will still not work. (This will throw a TypeError since doSomething is not a function at the time you call it)
As far as standard practices go, you should always use the proper tool for the job.
Axel Rauschmayer has a great post on scope and hoisting including es6 semantics: Variables and Scoping in ES6
Although using const to define functions seems like a hack, it comes with some great advantages that make it superior (in my opinion)
It makes the function immutable, so you don't have to worry about that function being changed by some other piece of code.
You can use fat arrow syntax, which is shorter & cleaner.
Using arrow functions takes care of this binding for you.
example with function
// define a function
function add(x, y) { return x + y; }
// use it
console.log(add(1, 2)); // 3
// oops, someone mutated your function
add = function (x, y) { return x - y; };
// now this is not what you expected
console.log(add(1, 2)); // -1
same example with const
// define a function (wow! that is 8 chars shorter)
const add = (x, y) => x + y;
// use it
console.log(add(1, 2)); // 3
// someone tries to mutate the function
add = (x, y) => x - y; // Uncaught TypeError: Assignment to constant variable.
// the intruder fails and your function remains unchanged
It has been three years since this question was asked, but I am just now coming across it. Since this answer is so far down the stack, please allow me to repeat it:
Q: I am interested if there are any limits to what types of values can be
set using const in JavaScript—in particular functions. Is this valid?
Granted it does work, but is it considered bad practice for any
reason?
I was motivated to do some research after observing one prolific JavaScript coder who always uses const statement for functions, even when there is no apparent reason/benefit.
In answer to "is it considered bad practice for any reason?" let me say, IMO, yes it is, or at least, there are advantages to using function statement.
It seems to me that this is largely a matter of preference and style. There are some good arguments presented above, but none so clear as is done in this article:
Constant confusion: why I still use JavaScript function statements by medium.freecodecamp.org/Bill Sourour, JavaScript guru, consultant, and teacher.
I urge everyone to read that article, even if you have already made a decision.
Here's are the main points:
Function statements have two clear advantages over [const] function
expressions:
Advantage #1: Clarity of intent When scanning through
thousands of lines of code a day, it’s useful to be able to figure out
the programmer’s intent as quickly and easily as possible.
Advantage #2: Order of declaration == order of execution
Ideally, I want to declare my code more or less in the order that I
expect it will get executed.
This is the showstopper for me: any value declared using the const
keyword is inaccessible until execution reaches it.
What I’ve just described above forces us to write code that looks
upside down. We have to start with the lowest level function and work
our way up.
My brain doesn’t work that way. I want the context before the details.
Most code is written by humans. So it makes sense that most people’s
order of understanding roughly follows most code’s order of execution.
There are some very important benefits to the use of const and some would say it should be used wherever possible because of how deliberate and indicative it is.
It is, as far as I can tell, the most indicative and predictable declaration of variables in JavaScript, and one of the most useful, BECAUSE of how constrained it is. Why? Because it eliminates some possibilities available to var and let declarations.
What can you infer when you read a const? You know all of the following just by reading the const declaration statement, AND without scanning for other references to that variable:
the value is bound to that variable (although its underlying object is not deeply immutable)
it can’t be accessed outside of its immediately containing block
the binding is never accessed before declaration, because of Temporal Dead Zone (TDZ) rules.
The following quote is from an article arguing the benefits of let and const. It also more directly answers your question about the keyword's constraints/limits:
Constraints such as those offered by let and const are a powerful way of making code easier to understand. Try to accrue as many of these constraints as possible in the code you write. The more declarative constraints that limit what a piece of code could mean, the easier and faster it is for humans to read, parse, and understand a piece of code in the future.
Granted, there’s more rules to a const declaration than to a var declaration: block-scoped, TDZ, assign at declaration, no reassignment. Whereas var statements only signal function scoping. Rule-counting, however, doesn’t offer a lot of insight. It is better to weigh these rules in terms of complexity: does the rule add or subtract complexity? In the case of const, block scoping means a narrower scope than function scoping, TDZ means that we don’t need to scan the scope backwards from the declaration in order to spot usage before declaration, and assignment rules mean that the binding will always preserve the same reference.
The more constrained statements are, the simpler a piece of code becomes. As we add constraints to what a statement might mean, code becomes less unpredictable. This is one of the biggest reasons why statically typed programs are generally easier to read than dynamically typed ones. Static typing places a big constraint on the program writer, but it also places a big constraint on how the program can be interpreted, making its code easier to understand.
With these arguments in mind, it is recommended that you use const where possible, as it’s the statement that gives us the least possibilities to think about.
Source: https://ponyfoo.com/articles/var-let-const
There are special cases where arrow functions just won't do the trick:
If we're changing a method of an external API, and need the object's reference.
If we need to use special keywords that are exclusive to the function expression: arguments, yield, bind etc.
For more information:
Arrow function expression limitations
Example:
I assigned this function as an event handler in the Highcharts API.
It's fired by the library, so the this keyword should match a specific object.
export const handleCrosshairHover = function (proceed, e) {
const axis = this; // axis object
proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); // method arguments
};
With an arrow function, this would match the declaration scope, and we won't have access to the API obj:
export const handleCrosshairHover = (proceed, e) => {
const axis = this; // this = undefined
proceed.apply(axis, Array.prototype.slice.call(arguments, 1)); // compilation error
};
I'm trying to learn Javascript by reading Eloquent Javacript. I'm on the chapter dealing with functions and I'm stuck trying to figure out how the code below works. I don't see how the add function ever gets called. I see them calling addTwo and addFive but those names are different than add. The result of this code being run is 9. Can someone please explain this to me.
function makeAddFunction(amount) {
function add(number) {
return number + amount;
}
return add;
}
var addTwo = makeAddFunction(2);
var addFive = makeAddFunction(5);
show(addTwo(1) + addFive(1));
In makeAddFunction, a function is created, called add. This function is returned.
makeAddFunction is called twice with 2 different parameters, and stored in two variables, addTwo and addFive.
Calling addTwo() and addFive() is calling the functions created by add(), with the "amounts" 2 and 5 respectively.
addTwo(1) + addFive(1) == (1 + 2) + (1 + 5) == 9
Sometimes these types of 'closures' are called Builders, or Factories. The makeAddFunction 'builds' a special version of add based on the parameter you pass to makeAddFunction.
The addTwo function would look like:
function addTwo(number) {
return number + 2;
}
The makeAddFunction create a closure that sets amount as whatever number you pass in and returns a function that will add that amount to whatever number you pass to the new function and return it.
My best advice is you try to learn a bit about Javascript closures. Really. I might not be the answer you are looking for, but it is the best you can do if you want to understand what's happening there.
Get yourself a copy of any good javascript book. Let me suggest 'Javascript - The Good Parts' by Douglas Crockford.
For some of us, Javascript closures were not something we grokked. I hope it's easier for you.
Anyway, makeAddFunctionis a function creator. It creates new functions which are tied to the parameter you passed to makeAddFunction. Therefore, the addTwo variable receives and stores a new function, which you can invoke later by appending parentheses to it, i.e. addTwo().
The parameter you pass to addTwo, i.e. 1on invokation addTwo(1) is passed to the add function, because addTwo is nothing more than an add function where the amount var has a fix value of 2.
var addTwo = makeAddFunction(2);
When you call makeAddFunction(2) initially, the amount var is within its function scope where add can see it. addTwo now is set to the add function that makeAddFunction(2) returned.
addTwo(1)
Remember addTwo is now set to what makeAddFunction(2) returned, which is the function add, and amount is set to 2 within makeAddFunction(2)'s scope. add just returns its argument (1), plus the amount (2) in makeAddFunction(2)'s scope.
The same goes for addFive(5).
Javascript Ninja or The Good Parts are good reads that explain closures in detail. I'd highly suggest picking up those.
Follow the SO Linked/Related Questions on the right. Anyway ..
This is explained the article, albeit with a lot of fluff. Anyway, with a bit of fluff-cutting here is a "annotated" version:
.. functions [do] not just package up [some code to run], but also an environment. [..] a function defined inside another function retains access [to lexical variables (like "amount")] that existed in [the outer function] at the point when [the inner function] was defined.
Thus, the [inner] add function in the above example, which is created when makeAddFunction is called, captures an environment [including the "amount" variable of the outer function]. It packages this environment, together with [the code to run], into a value [(which is a fancy way to say functions are just objects)], which is then returned from the outer function.
When this returned function ([which has been assigned to] addTwo and addFive) is called, [the called function has access to] the captured environment ([and the "amount" variable which still contains the value initially passed to makeAddFunction]). These two values ([which are currently named by] "amount" and "number") are then added, and the result is returned.
I am not found of the original usage of "value" and have edit those parts a good bit - in JavaScript, variables (not values) are bound in closures.
Javascript relies pretty heavily on higher-order functions. Functions can be returned, assigned to variables, and passed around as values. This comes in handy in a lot of situations, especially when dealing with evented programming (JS's direct lineage from the its most prolific implementation in the browser.)
http://en.wikipedia.org/wiki/Higher-order_function
What you are seeing is a function that creates a function. It could be considered a "factory" for a function with one preset argument.
While writing javascript, one can define a method in 3 different ways.
1] A function in global namespace
function doSomething();
2] A function that is member of a function
function Clazz() {}
Clazz.doSomething = function(){};
3] A function that is memeber of the instance of function
function Clazz() {}
Clazz.prototype.doSomething = function(){};
Depending upon the code organization, one can choose one of the above methods over others.
But purely from performance standpoint which is the most efficient one? (especially between 1 and 2)
Will your answer be different if doSomething has arguments?
From a pure performance POV, 1 should be the fastest. The reason being that it would require less work to setup the scope chain & execution context. Also if you access any global variables from within the function, the resolution will be fastest with 1, again simply because of the depth of scope chain.
As a general rule further up (near to the global) an object is in the scope, the faster it is. for the same reason accessing property a.b will be faster than accessing a.b.c
The performance gain might not be too much in case of a simple function call, however it can mount up if say you call the function n a loop.
None of those declarations do the same thing and aren't interchangeable, what kind of comparison do you expect? It's like asking if it's faster to instantiate 10 variables or an array with 10 items: one is fastest, but the result is not the same.
You cannot compare performance between the function declarations,
For example add(a,b) functions declared in all the 3 places give the same performance. performance matters by how you write your code, not by where you declare your functions...
you are missing the most optimized one:
var x = function(){}
When javascript sees the definition:
function x(){}
It then converts it into the former form. If you do it that way in the first place there is a negligable speed up. But for the sake of answering your question, this is the most optimal.