I see that babel.js decorators (available in "stage 1") implement the spec at https://github.com/wycats/javascript-decorators. It appears that decorators are limited to (1) classes, (2) accessors, and (3) methods. In my case, I want to use decorators on plain old functions, as in
#chainable
function foo() { }
where (just an example)
function chainable(fn) {
return function() {
fn.apply(this, arguments);
return this;
};
}
I don't see any logical reason why decorators should not be able to apply to functions. My question is, is there some way to accomplish this? Or is there some good reason why functions cannot be decorated?
It turns out there is an issue raised for this at https://github.com/wycats/javascript-decorators/issues/4.
To execute a decorator, you evaluate an expression and doing that prevents hoisting (even for a variable declaration, the right-hand side of an assignment stays put). Therefore, it is not compatible with function declarations being hoisted.
As a work-around, I suggested that function expressions, generator function expressions and arrow functions could be enabled to be decorated:
const func = #someDecorator('abc') (x, y) => { return x + y };
Alas, that wasn’t met with much enthusiasm: Decorators for functions
You certainly have a point here.
But as neo_blackcap pointed out, function decorator are not part of the ES7 decorators draft.
So, the best thing you can do is to start discussion on the corresponding tracker to attract community attention to your proposal.
ES7 decorators are on their first stage of development second stage of development, meaning that their API is still under development and could undergo any change.
I think the problem is function decorator has not been ES7 draft.
Of course, you still can implement your function decorator by yourself
Related
Apologies if this seems like a beginner question, I am currently learning Javascript and have come across different ways of structuring function declarations. An example below
function mapStateToProps(state) {
console.log(state);
}
const mapStateToProps = state => {
console.log(state);
}
What is the benefit of using one or the other; in which situation would you use one over the other?
Arrow functions are the new ES2015 syntax, for me the main difference is changing this context you may read about it here https://medium.com/#thejasonfile/es5-functions-vs-es6-fat-arrow-functions-864033baa1a
The first example is a function declaration and the second example is a function expression. The second example you provided only serves to provide more concise JavaScript code to the first example and doesn't really capture the idea of your question of when to use ES6 arrow functions over function declarations. In other words your example, is just syntactic sugar, in your examples, nothing is really solved, just more concise code.
A better example is the following:
const team = {
members: ['Dolly', 'Billy'],
teamName: 'Hacking Crew',
teamSummary: function() {
return this.members.map(function(member) {
return `${member} is on team ${this.teamName}`;
});
}
};
console.log(team.teamSummary());
Run this snippet and you will see the error. Now, this error does not have to be solved with the arrow function, there are a couple of ways to solve it, but your question of in which situation would you use one over the other, this is a good use case for using an arrow function to solve this error.
Before I provide the solution, understand that fat arrow functions make use of what is called the lexical this. I will provide the refactor below and then unpack my previous sentence:
const team = {
members: ['Dolly', 'Billy'],
teamName: 'Hacking Crew',
teamSummary: function() {
return this.members.map((member) => {
return `${member} is on team ${this.teamName}`;
});
}
};
console.log(team.teamSummary());
Lexical means the placement of this term depends on how its interpreted or how its evaluated. So, depending on where we are placing the word this will change when using a fat arrow function.
When we use a fat arrow function and make reference to this inside of it this is automatically set equal to this in the surrounding context which in this code snippet is the team object.
So if lieu of using .bind(this) and having to cache a reference to this, you can replace fat arrow function as a solution.
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
};
In JavaScript, you can name lambda functions
(function() {
...
}).call()
doSomething(param1, param2, function() {
...
});
like
(function main() {
...
}).call()
doSomething(param1, param2, function callback() {
...
});
So they are not anonymous and error tracing becomes clearer to the programmer -- especially useful with Node.js to avoid (or at least understand) callback hells.
I am currently getting into CoffeeScript to try and see if it makes my coding clearer/faster, but can't get around to naming throw-away functions like these ones.
(->
...
).call()
doSomething param1, param2, ->
...
Is there a way to name these functions in CoffeeScript? Although not critical, I would see that as a big fault in CS.
I got my answer from here.
Basically, you can't do that -- CoffeeScript does not allow the naming of functions. They say it's because of IE9 compatibility, but what if you don't really care about that? (Come on, even low information users nowadays know IE8 and lower aren't meant for use, and in my personal opinion those browsers died together with Win XP.)
Back to the answer, CoffeeScript only accepts function expressions, as opposed to declarations -- meaning I can't name a lambda function unless I assign it to a var and pass it as a parameter later.
Also discussed in the FAQ: Q: Is there any way to name functions, for reflection and recursion?
https://github.com/jashkenas/coffee-script/wiki/FAQ
It lists a number of related repository issues, including:
https://github.com/jashkenas/coffee-script/issues/366
Just experimenting with different inheritance techniques in JS, and came across something mildly discomfiting about Crockford's Prototypal Inheritance pattern:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
var C,
P = {
foo:'bar',
baz: function(){ alert("bang"); }
}
C = object(P);
It's all good - except when you log to console - the object appears as F. I've seen classical emulation in which you can repoint the constructor - is there a similar method to coerce the objects (console) reference?
The issue is that it's referring to the name of the constructor function. This quickly becomes a discussion about function expressions and statements and the name property. Turns out is is completely impossible to create a new named function at runtime without using eval. Names can only be specified using a function statement function fnName(){} and it's not possible to construct that chunk of code dynamically aside from evaling it. var fnExpression = function(){} results in an anonymous function assigned to a variable. The name property of functions is immutable so it's a done deal. Using Function("arg1", "arg2", "return 'fn body';") also only can produce an anonymous function despite being similar to eval.
It's basically just an oversight in the JS spec (Brendan Eich stated he regrets defining the display name the way he did 10 or so years ago) and a solution is being discussed for ES6. This would introduce more semantics for deriving a function's display name for debug tools or perhaps an explicit way to set and adjust it.
For now you have one route: eval, or some other form of late execution of configurable code. (eval by any other name...)
function displayName(name, o){
var F = eval("1&&function "+name+"(){}");
F.prototype = o;
return new F;
}
The function statement alone won't return from eval, but doing 1 && fnStatement coerces the thing into an expression which is returnable.
(Harmony Proxies also allow setting up functions that report names which you can configure without eval but that's not usable except in Node.js and Firefox currently).
I'll make a note here that all those "evil" functions that have been shat upon by Crockford and many others ALL have their place. eval, with, extending natives all enable specific techniques which are otherwise completely impossible and it's not wrong to use them when the occasion is right. It's just likely that most people aren't qualified to make the judgement of when that time is right. In my opinion using eval harmlessly to make up for poor language semantics and tools while waiting for a solution is perfectly acceptable and won't cause you any harm as long as you're not funneling arbitrary code into that eval statement.
If I log the object I can see: Object { foo="bar", baz=function()}, so I don't understand your problem...
Anyway, can use Object.create() instead of Crockford's function:
var P = {
foo:'bar',
baz: function(){ alert("bang"); }
}
var C = Object.create (P);
console.log (C):
Object { foo="bar", baz=function()}
Taking the jQuery framework for example, if you run code like this:
$(document).ready(function init() { foo.bar(); });
The stack trace you get in Firebug will look like this:
init()
anonymous()
anonymous([function(), init(), function(), 4 more...], function(), Object name=args)
anonymous()
anonymous()
As you can see, it's not very readable, because you have to click on each function to find out what it is. The anonymous functions would also show up as (?)() in the profiler, and they can lead to the "cannot access optimized closure" bug. It seems to me that these are good reasons to avoid them. Then there's the fact that ECMAScript 5 will deprecate arguments.callee in its strict mode, which means it won't be possible to reference anonymous functions with it, making them a little less future-proof.
On the other hand, using named functions can lead to repetition, e.g.:
var Foo = {
bar: function bar() {}
}
function Foo() {}
Foo.prototype.bar = function bar() {}
Am I correct in thinking that this repetition is justified in light of the debugging convenience named functions provide, and that the prevalence of anonymous functions in good frameworks like jQuery is an oversight?
I agree there are certain downsides to using anonymous methods in JavaScript/EMCAScript. However, don't overlook how they should be used. For simple one liners that you want to pass to another function, they are often excellent.
I found the answer to my question in this very informative article. Firstly, it turns out that I was right about named functions being more desirable, but the solution is not as simple as adding identifiers to all anonymous functions. The main reason for this is JScript implementing function expressions in a very broken way.
Secondly, there is a distinction between function statements and expressions. An anonymous function is just a function expression with the identifier omitted, and adding an identifier (naming it) wouldn't make it a statement (except in JScript, which is why it's broken). This means that all of the other answers were off mark.
But for me anonymous functions are more readable in the source code, because I am sure they are only used there.
Anonymous functions are very convenient. A better fix to this problem, instead of naming the functions, would be if firebug told you on which line in which file the anonymous function was created.
init()
anonymous() // application.js, line 54
anonymous() // foo.js, line 2
And the stack trace is the only place where anonymous functions are a problem imo.