-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Docs: Update JavaScript guidelines to reflect current best practices #9037
Conversation
Prefer JSDoc documentation
Slightly updated since ES5.1
Exception removed in #5829
Instead defer to external resources
Discourage disabling rules, because you’re probably wrong if you’re disabling a rule
Specific to WordPress?
Perhaps controversially, but I argue that complex ternaries are difficult to read. While I did not include any guidelines _against_ using complex ternaries, I similarly don’t think it’s advisable that we include recommendations for how to use them.
Test live: https://calypso.live/?branch=update/js-docs |
|
||
## Iteration | ||
|
||
The functional programming inspired methods that were added in ECMA5 improve readability. Use them throughout. | ||
|
||
```js | ||
var posts = postList.map( function( post ) { | ||
const posts = postList.map( function( post ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use an arrow function here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use an arrow function here?
Done in d7b075a
when: 4, 'you are': 15 }; | ||
|
||
map = { ready: 9, | ||
when: 4, 'you are': 15 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two ideas:
- use
const
-first thinking as an example instead - not name this
map
in order to prevent confusion fromArray.prototype.map
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two ideas:
Yeah, I went back-and-forth a few times with the const
. I agree we should promote it, but I didn't want to confuse by having const
for the same variable name multiple times in the same example block. I might see to using different variable names, or just creating separate code blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lots of these are good
vs bad
, so I think it's reasonable to assume when reading that we're comparing two things that don't exist together
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use
const
-first thinking as an example instead
not name thismap
in order to prevent confusion fromArray.prototype.map
Improved examples, including separate code blocks with const
instead of let
, in ffedbac.
} | ||
|
||
// Unlike jQuery, WordPress prefers a space after the ! negation operator. | ||
// This is also done to conform to our PHP standards. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you for removing this!
$( '.container' ).val( array[ i ] ); | ||
for ( let i = 0; i < 100; i++ ) { | ||
object[ array[ i ] ] = someFn( i ); | ||
$( '.container' ).val( array[ i ] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh my. I hope to never find this actual code in a review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh my. I hope to never find this actual code in a review
Removed this specific line in 4d171dd . This could also be improved to a reduce
or forEach
, but I think the point is to demonstrate for
spacing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I got the point of it, but was just a bit irked that we used such a nasty example. we could have used a much simpler loop body
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I got the point of it, but was just a bit irked that we used such a nasty example. we could have used a much simpler loop body
I'm going to leave this as-is, but d7b075a includes an emphasis on ES5+ Array methods for iteration.
@@ -125,54 +123,105 @@ Indentation and line breaks add readability to complex statements. | |||
|
|||
Tabs should be used for indentation. | |||
|
|||
Try to return early from a function to avoid deeply tabbed functions akin to ["Callback Hell"](http://callbackhell.com/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe deep indentation
would be more appropriate than tabbed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe
deep indentation
would be more appropriate thantabbed
Updated in e3b41c4.
thanks for taking the time to update these @aduth. overall I think it would be great to place more emphasis on |
@dmsnell : We have a short section "Iteration" that we could expand to cover more use-cases of |
Improved "Iteration" section with an emphasis on ES5+ Array methods in d7b075a. |
map = { ready: 9, | ||
when: 4, 'you are': 15 }; | ||
const labels = { facebook: 'Facebook', | ||
twitter: 'Twitter', 'google-plus': 'Google Plus' }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha, I almost made a comment like, "what are you thinking?" and then I noticed this is the "bad" example 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
haha, I almost made a comment like, "what are you thinking?" and then I noticed this is the "bad" example 😉
Yeah, I rearranged all of the examples to show "Bad" first.
```js | ||
// After | ||
const sumLabel = `The sum of ${ a } and ${ b } plus ${ c } is ${ a + b + c }`; | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
w00t! I ❤️ this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
w00t! I ❤️ this!
Thanks! As I was changing the original in "Multi-line Statements" to use const
, I felt depressed that we'd concatenate a string like that, so I thought it was a nice progression to see how the same example can be improved further using template literals.
@@ -420,6 +402,18 @@ const myStr = "You're amazing just the way you are."; | |||
const component = <div className="post"></div>; | |||
``` | |||
|
|||
[ES2015 template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) are available as an alternative to string concatenation when including variables in a string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is this obscure usage of tag functions with template literals. Do we want to acknowledge them and make some styling decisions?
function tag(strings, ...values) {
return {
blog: values[0],
user: values[1]
}
}
const s = tag`Make blog ${ 'catbacon' } with user ${ 'Porkat' }`;
// s === {
// blog: 'cat bacon',
// user: 'Porkat'
// }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is this obscure usage of tag functions with template literals.
I personally feel we should avoid advocating their usage. That is... unless we ever adopt Relay 😉 (reference)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't agree more (about not using them)
|
||
- [Rest](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) at MDN | ||
- Use [stateless function components or the `React.Component` class](https://facebook.github.io/react/docs/components-and-props.html#functional-and-class-components) instead of `React.createClass` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do we do about mixins? Are we encouraged to replace them by HoC when we think It's appropriate?
For example, LinkedStateMixin
and dirtyLinkedState
can be replaced nicely with a HoC, I think.
What's our current approach with that? Maybe we could add a note about mixins on this doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We definitely want to avoid all mixins, and LinkedStateMixin
has been on the black list for a long time. We have various ways to remove them: higher order components for sure, but also for some things local component state or proper use of our Redux state/query components
## Strings | ||
|
||
Use single-quotes for string literals: | ||
|
||
```js | ||
var myStr = 'strings should be contained in single quotes'; | ||
const myStr = 'strings should be contained in single quotes'; | ||
``` | ||
|
||
When a string contains single quotes, they need to be escaped with a backslash (\\): | ||
|
||
Double quotes can be used in cases where there is a single quote in the string or in JSX attributes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we not have a style preference one way or another for that? I personally think the latter is much more readable.
'The Cat\'s Hat'
vs
"The Cat's Hat"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally agree with your preference. If there's enough in agreement, I'd be okay with removing the allowed double-quote exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused here... I read @gwwar's comment as preferring "The Cat's Hat"
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@blowery : Oh, you're right, I misread it. In which case then... I disagree 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely prefer "The Cat's Hat"
over 'The Cat\'s Hat'
and I also prefer (backtick)The Cat's Hat(backtick)
over it too.
Why escape things when we don't have too? Just gets in the way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm with @gwwar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why escape things when we don't have too?
Consistency for one. Also, what happens when the string is updated and no longer needs escaping? Do we change the "
back to '
? This seems easy to overlook and is unnecessary effort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consistency seems subjective here. What are we being consistent about: quote types or escaping quotes?
If we're consistent about quote types then we're basically requiring that we never use double-quotes, except for with JSX.
If we're consistent about escaping, we're saying never escape quotes (except maybe the back-tick inside of template literals).
In this case I'm willing to sacrifice a small consistency for the sake of providing normal-reading sentences.
👍 Thanks for updating this @aduth ! |
// Bad | ||
const sumLabel = 'The sum of ' + a + ' and ' + b + ' plus ' + c | ||
+ ' is ' + ( a + b + c ); | ||
```js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a heads up, looks like a couple of extraneous '```js's got in - causes the output to look like:
// Bad
const sumLabel = 'The sum of ' + a + ' and ' + b + ' plus ' + c
+ ' is ' + ( a + b + c );
```js
```js
// Good
const sumLabel = 'The sum of ' + a + ' and ' + b + ' plus ' + c +
' is ' + ( a + b + c );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 good catch!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch indeed, fixed in cb8cf91
Unless folks have found any blockers, I think this is a great improvement, and we should |
I'm sure there's still room for improvement, but we can always revisit it in a future pull request. Hopefully nothing changed here was too controversial. Seems a few ideas to consider for a future pull request are:
In the meantime, I'm going to squash and merge this one. |
…9037) * Docs: Update var to let/const in JS guidelines * Docs: Remove inline comments on parameter list Prefer JSDoc documentation * Docs: Add caveat about typeof object * Docs: Update truthy link to ES2015 specification Slightly updated since ES5.1 * Docs: Add explanation for boolean return value function naming * Docs: Fix object key spacing per guidelines Exception removed in #5829 * Docs: Add link for Yoda conditions reference * Docs: Improve React component best practices * Docs: Remove ES6 usage examples Instead defer to external resources * Docs: Add reference links for ESLint configuration Discourage disabling rules, because you’re probably wrong if you’re disabling a rule * Docs: Add note about EditorConfig * Docs: Remove jQuery clarification Specific to WordPress? * Docs: Add early return example * Docs: Add else return example * Docs: Remove complex ternary example Perhaps controversially, but I argue that complex ternaries are difficult to read. While I did not include any guidelines _against_ using complex ternaries, I similarly don’t think it’s advisable that we include recommendations for how to use them. * Docs: Add window typeof check tip for SSR * Docs: Add caveat about object "in" operator * Docs: Improve clarity of `else` `return` guideline * Docs: Use tabs consistently in JS docs * Docs: Promote discussing lint rules * Docs: Use consistent capitalization in comments * Docs: Deeply tabbed -> deep indentation * Docs: Remove jQuery specific spacing example * Docs: Use arrow functions where applicable * Docs: Add link for automatic semicolon insertion * Docs: Improve examples naming, logic, ordering * Docs: Emphasize ES5+ Array methods for iteration * Docs: Include template literal example * Docs: Fix closing code block syntax
This pull request seeks to update our JavaScript guidelines to reflect consistent best practices throughout.
Much of this should be non-controversial:
var
tolet
/const
React.createClass
toReact.Component
'valueOf' in object
, early function returns,typeof object === 'object
Other changes may warrant debate: