-
Notifications
You must be signed in to change notification settings - Fork 26.4k
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
Using 'ForInStatement' is not allowed (no-restricted-syntax) #851
Comments
I was literally thinking the same 20 minutes ago and couldn't see any mention of this in the README. |
https://github.com/airbnb/javascript#iterators--nope Use things like Feel free to provide some loops (ideally concrete use cases and not contrived examples), and I'll happily show you a better way to write the code with iteration instead of a loop. |
Of course, but maybe this should be added to the README under Objects? |
PRs are welcome to improve the documentation. |
@ljharb thank you very much |
my loop was like this: for (const i in options) {
if (opts && opts.hasOwnProperty(i) && options.hasOwnProperty(i)) {
options[i] = opts[i];
}
} and it is now like this: Object.keys(options).forEach((key, index) => {
if (opts && opts.hasOwnProperty(key)) {
options[key] = opts[key];
}
}); is there a better way? |
@francoisromain |
@ljharb oh wow! : ) |
@ljharb it's not really the right place to ask, here is an unrelated question: Is there a better syntax for this one? if (value) {
options.value = value;
} Thank you |
@francoisromain no, that is the proper way to do it, so that you only perform an assignment in the case where the conditional is true. |
@ljharb ok thanks |
Another one for you @ljharb :)
|
const count = Object.values(this.state.selected).filter(Boolean).length;
/* or, if you really need to only check for literal true */
const count = Object.values(this.state.selected).filter(x => x === true).length; |
if use for-in/ for-of with async generator function, how to change it? Promise.coroutine(function*() {
const files = ['f1', 'f2', 'f3'];
for (let file of files) {
yield fs.readFileAsync(file);
}
}) By the way, this code can be replace into async-await style in ES7 syntax. |
I don't know what For the body of the generator though, |
Or, with
|
There are a few instances where for...in statements are useful, here is one. If you're using generators for async code (as in the case of Co.js and Koa), You can do this..
That works, but now if you want to make it async this won't work.
You can go back to this..
|
It's worth noting that the styleguide doesn't allow generators, so if you're overriding that rule for you project, you could also override the for-in rule. |
Yea, well not allowing generators was all kinds of silly being that they're the easiest path to upgrading to async/await, and babel is a pain in the rear for development. |
Even with generators, you never want |
So what is one supposed to do if they want to iterate over all enumerable properties of an object, not only their own properties? I don't see any solution besides a very cumbersome The problem with the |
@mhofman I'm curious, what's your use case for wanting inherited properties? In general, the thing you want is an ES spec proposal: |
My use case is a logging library that enumerates over all properties to log them. I agree it's pretty rare to actually have to use |
If eslint added a more specific way to block for-in loops or an easier way to override it, I'd be all for that - but imo the annoyance of overriding it for a small handful of edge cases is worth the benefit of never having to see a for-in loop anywhere else :-) |
@ljharb 👋 how about... const aliases = {
'@': 'src',
shoelace: path.resolve(__dirname, 'src/components/shoelace'),
}
function resolveSrc(_path) {
return path.join(__dirname, _path)
}
function registerWebpackAliases() {
const webpackAliases = {}
for (const [alias, aliasPath] of Object.entries(aliases)) {
webpackAliases[alias] = resolveSrc(aliasPath)
}
return webpackAliases
} |
return Object.fromEntries(Object.entries(aliases).map([
alias,
aliasPath,
] => [
alias,
resolveSrc(aliasPath),
])); (See https://npmjs.com/object.fromentries if you need to polyfill it) |
@ljharb Is it possible to convert a function that has async sleep?
PS: |
@robot110011 postLinks
.reduce(
async (previousPromise, post) => {
await previousPromise;
likePost(post);
return sleep(3000);
},
Promise.resolve(),
) |
Wow thanks @karol-majewski ! Not good to read tough |
Is this loop acceptable by the guide?
|
@robot110011 there's no "sleep" in JS; i'd name that postLinks.reduce((prev, post) => prev.then(() => likePost(post)).then(() => sleep(3e3), Promise.resolve()); All loops are discouraged by this guide. |
Really appreciate the lesson! Cheers |
Early returning in a loop is the use case for using
|
@crobinson42 for those use cases, it's better to use (or build) an iterating abstraction like |
It might be worth to notice: there are things that can't be (easily) done with |
@rodrigoabb some/every/find/findIndex short-circuit, ftr. show me some code that you think can't be easily done with iteration methods, and i'll be happy to supply you with code that is. |
This thread is already 3 years old and you're still teaching and helping people out with their iterations. You're such a good sport, @ljharb. |
I know it's an old thread, but I was wandering how to rewrite this const result = products.flatMap((obj) => {
const parts = [{}, {}];
for (const key in obj)
parts[key.startsWith('user') ? 1 : 0][key] = obj[key];
return parts.filter((value) => Object.keys(value).length !== 0);
}); In this case const products = [{
"listPrice": 50,
"discount": 10,
"total": 45,
"users": "",
"userNumber": 10,
"userlistPrice": 120,
"userDiscount": 10,
"userTotal": 108
},
{
"listPrice": 1000,
"discount": 10,
"total": 900,
"userNumber": 100,
"userlistPrice": 1200,
"userDiscount": 0,
"userTotal": 1200
}] |
function split(array, predicate) {
return array.reduce(([a, b], item) => {
if (predicate(item)) {
return [a, b.concat(item)];
}
return [a.concat(item), b];
}, [[], []]);
}
const result = products.flatMap((obj) => {
const parts = split(Object.entries(obj), ([k]) => k.startsWith('user'));
return parts.filter((v) => v.length > 0).map(Object.fromEntries);
}); maybe something like this? |
Hi @ljharb, I woudlike to know your opinion about how to rewrite this code? The main point is that I need process chunks in series, const chunks = [ ['url1', 'url2'], ['url3', 'url4']];
for (const chunk of chunks) {
await Promise.all (
chunk.map( url => fetch(url)
)
} |
chunks.reduce(async (prev, chunk) => {
await prev;
return Promise.all(chunk.map(url => fetch(url)));
}, Promise.resolve()); if you need the fetched data, it'd be a little different, but your snippet doesn't save that info, so neither does mine. |
@ljharb Thank you for answer. In personal for me (await prev and Promise.resolve() as initial value) - looks a non-obvious Do you agree with me? ) |
Nope. I think the harm caused by loops is far outweighed by the slightly less intuitive reduce form above. |
:) Hmm... interesting |
@mkovel http://qr.ae/RNMEGA and https://gist.github.com/robotlolita/7643014 are worth a read. Happy to discuss further in the gitter channel if you have further questions, since it's related, but off topic, for this issue. |
@ljharb
I'm curious how would one make this more concise, or at least make it eslint rule compliant. |
Ok nevermind, I found it:
|
props.stories.forEach(({ id }) => progressTracker.value[id] = 0) Does this work? |
@EmilyRosina
thanks for the hint (it's much more readable than my previous try). |
Since version 8, there is this error on for in loops.
What should be used in place of for-in loops ?
Thanks
The text was updated successfully, but these errors were encountered: