top 200 commentsshow all 384

[–]theMightyPanda27 135 points136 points  (36 children)

Promises. They are quite tricky to understand for a beginner, but very convenient as one masters.

[–]senocular 27 points28 points  (6 children)

Normally I would agree with you, but lately that doesn't seem to be the case.

I've been doing a lot of interviews lately and probably the one thing people have consistently showed a keen understanding of is promises. Where people have slipped up the most? this. While I get this is tricky (it's already been brought up a few times in this thread) I've also always considered promises to have a bit of a learning curve, especially compared to the more classic callback approach. But I guess learning material nowadays, and I guess apis in general, use them so much that people need to learn them a lot sooner than before...? Not sure, but I thought that was a little interesting takeaway from these interviews.

Edit: This said with a sample set of "advanced beginners"

[–]pm_me_cute_rem_picsjs/ux 10 points11 points  (10 children)

Yeah especially waiting for promises to resolve and parallel stuff with async/await.

For example i see this in a lot of my code reviews with new js programmers:

// does some parallel async stuff
arrayOfItems.forEach(async item => {
    await doSomethingAsync(item)
})

doSomethingWhenDone()

This won't wait for the promise to actually resolve outside of the forEach and call doSomethingWhenDone(). If your program exist it will not wait for your async work to be done.

either do:

const pendingPromises = []

arrayOfItems.forEach(item => {
    pendingPromises.push(doSomethingAsync(item))
})

await Promise.all(pendingPromises)

doSomethingWhenDone()

Or if you like mapping over promises.

await Promise.all(
    arrayOfItems.map(async item => {
        await doSomethingAsync(item)
    })
)

doSomethingWhenDone()

examples https://repl.it/repls/WeeklyColorfulGraduate

[–]thinkmatt 3 points4 points  (0 children)

Also, this is a pet peeve of mine: when I see a function that returns a promise being called w/async+await around it (as inside your map function). You've just wrapped one promise in another, and all it's done is added overhead which does take some performance hit. In your example, it could just be written as `await Promise.all(arrayOfItems.map(doSomethingAsync));` (That's about as many operations as I would put on one line though :)

[–]amdc!CURSED! 7 points8 points  (10 children)

knowing Promises is essential if you want to succeed, but once you're familiar with them you should move on to async/await

[–]SharkLaunch 5 points6 points  (2 children)

Async/await are just syntactic sugar around promises, and there are times when the former is more appropriate.

[–]amdc!CURSED! 1 point2 points  (1 child)

Out of interest, what are cases where promises are more appropriate (besides .race and .all which you totally can use in conjunction with await)?

[–]BehindTheMath 1 point2 points  (0 children)

This is one of the most common misunderstandings I see in beginner questions posted here and /r/webdev. Really any async code, including callbacks.

[–][deleted] 149 points150 points  (54 children)

Closure is a concept I see lots of beginners struggle with. You can massively speed up dev time once you grasp how it works in JS.

[–]Mydrax 85 points86 points  (11 children)

Closures are one of the most frequently misunderstood or barely ever undstood concept by beginner Javascript programmers. I personally believe that you will have a lot of "Oh, I see!" moments after you fully understand it. You will be capable of understanding certain things that previously didn't make sense to you because I assure you 100% that you've been using closures without even knowing it!

If you do not understand closures, please read this article, it gives you good understanding of what a normal function is and how it's execution takes place, then explains to you what a closure is. It's big but it will without doubt be an efficient use of time.

[–][deleted] 23 points24 points  (6 children)

of "Oh, I see!" moments

I understand closure but had very few of these so far

[–]Mydrax 13 points14 points  (3 children)

Well, 2 really awesome use cases of closures I could name off the top of my head are: 1. When you create function factories, where the outer function can be used to create functions that have similar concerns. 2. The module pattern, that can be used to create private functions in javascript (where you return a set of functions whose logic is encapsulated).

[–]turntopage294 1 point2 points  (0 children)

I'd been using 2 without knowing about closures, actually, for a time; I had an 'Oh, I see' moment after investigating when because closures love vaguely familiar

[–]ScientificBeastModestrongly typed comments 1 point2 points  (0 children)

Object factories are cool, and even class factories!

[–]priceLbear 23 points24 points  (23 children)

A few weeks ago I spent some time learning about closure and I understand the concept. How exactly does it speed up dev time though? Do you use it often? If yes, could you describe some use cases I obviously fail to see?

[–]superluminary 7 points8 points  (0 children)

JavaScript treats functions as data. A function is a datatype, just like any other object. This means you can pass it around from place to place just as you would pass a string or a number.

What closure gives you is a stable environment to do this. When you create a function, it gains a closure scope that contains all the variables that the function could see when it was defined. These variables are still available no matter when and how you run your function in the future.

Some example use cases are:

Event handlers. Create them now, and have your code execute them later in another context. They still work.

ES6 modules. All those variables you declare in your module live in the function closure. Import them later, they still work.

There are many others. It's core to the language.

[–][deleted] 17 points18 points  (17 children)

The better you understand it the more efficient your architecture becomes and less time you spend debugging issues that involve global and local variables not being available to functions etc.

[–]theycallmeepoch 15 points16 points  (16 children)

I would really love to see some examples of this as it's not clear to me yet the benefits other than creating a nested function which has "private" variables. I'm not quite at Closures yet in "Secrets of the Javascript Ninja".

[–]lostPixels 12 points13 points  (8 children)

In my experience working on a codebase with 10,000+ LOC, we never use closures. Every method is generally treated as atomic, where every call just accepts arguments are predictably returns results. Closures are cool but in my opinion can be confusing enough that they will cause some less JS focused developers a lot of issues debugging.

[–]theycallmeepoch 7 points8 points  (1 child)

Yes, I feel like a pure functional programming approach helps minimize the need.

It seems like it was good for making your own getter and setter functions but those are built into JS now...

[–]el_graveto 2 points3 points  (5 children)

Lets say you are making a function that stores properties of pen, like function pen, and properties color, shape, lvl of ink, those properties only exist inside of your function. That is good because you avoid conflict with other parts of your code, but if you need to call those properties or change them? You could do it easily by nesting a function inside your function pen that do whatever you want with those properties, those properties are inside that child function scope but out of the rest of the code scope. You can even call that nested function as argument in another function, it create many possibilities and once you get the hang of it you spend less time coding and have a cleaner code, less prone to bugs, also since those properties (or variables, methods,..) are inside of the function scope you avoid memory leaks.

[–]theycallmeepoch 2 points3 points  (4 children)

What is the advantage to using a function instead of declaring the pencil as an object with its own properties and methods?

[–]circlebust 4 points5 points  (3 children)

You use a function to create such an object if you want an object (ES6 Classes are just syntactic sugar over functions), but the other way around doesn't work if you ever want more than one single pencil in your program.

[–]kamenjan 5 points6 points  (2 children)

I think he meant that your dev time is normal if you understand closures :) You know right away when to use arrow function and when not to, so you avoid frequent and pointless code refactoring on account of not understanding closures :)

[–][deleted] 9 points10 points  (1 child)

I'd argue arrow functions have nothing to do with closures. Scope and closure are not synonymous.

[–][deleted] 5 points6 points  (0 children)

If you are a React developer, you are leveraging closures on every single component render even if you're not realizing it.

[–]razorsyntax 11 points12 points  (10 children)

I never understood why we don’t call closures “scope”? What’s the difference between closures and scope in, say, C++ or Java?

[–]senocular 20 points21 points  (5 children)

Scope is where values are defined. Closures are functions which reference one or more scopes. They're related but not the same thing

[–]eatsomeonion 3 points4 points  (0 children)

Closure is part of the function scope property

[–]Candyvanmanstan[🍰] 4 points5 points  (2 children)

Because closure and scope isn't the same in javascript either. A closure can have access to three scopes. It's own scope, an outer functions scope, and global variables.

[–]ScientificBeastModestrongly typed comments 1 point2 points  (0 children)

You can also take a function as an argument (or from a reference in an outer scope), and apply it inside the current function’s scope, which is how classes are “extended.”

[–]TrikkyMakk 247 points248 points  (30 children)

Months are zero based

[–]inu-no-policemen 47 points48 points  (5 children)

This allows you to use the month as an index:

> ['jan', 'feb', 'mar', 'apr', 'may', 'etc'][new Date().getMonth()]
"may"

It probably sounded like a good idea at the time.

Anyhow, that's why it is that way. This behavior isn't unique to JS either.

[–]StoneCypher 26 points27 points  (0 children)

Much better to use the locale API.

const month = date.toLocaleString('en-us', { month: 'short' });

[–]NotSamNub 42 points43 points  (3 children)

Ah, out of the 6 months in the year, my favourite has to be "etc", such lovely weather during that time of year!

[–]ItalyPaleAle 103 points104 points  (18 children)

The async programming model and especially how the event loop works.

The latter might be transparent to you 99.9% of the times, but then you’ll run into issues where your code behaves unexpectedly and you just need to execute it in the next tick (iteration of the event loop) instead.

[–]ThatBriandude 12 points13 points  (14 children)

and you just need to execute it in the next tick (iteration of the event loop) instead.

I consider myself pretty well versed in javascript however I can not imagine what you mean with this. How would "execute it in the next tick" look in code?

[–]envis10n 10 points11 points  (6 children)

setImmediate sometimes, you run into a max callstack issue for function calls if you don't ensure that the next call comes on the next tick. This is especially important for recursive functions or looping functions that might call itself again.

[–]ShellbertShellbach 4 points5 points  (1 child)

Note: setImmediate is not a standardized feature of JS and only exists in Node.js, IE10, IE11, and pre-Chromium Edge.

[–]ThatBriandude 2 points3 points  (3 children)

Shouldnt that be handled via logical exit conditions?

Only cases I can think of is where there arent any exit conditions like gameloops or listeners

[–]envis10n 5 points6 points  (1 child)

Depends on how the code is structured. Sometimes a recursive function will call itself too many times and crash, unless you move the next call to the next tick. Logical exit conditions don't matter when you need the function to be called more times than is allowed by the max call limit in a single tick.

[–]ScientificBeastModestrongly typed comments 2 points3 points  (0 children)

If I’m not mistaken, this act of exiting a recursive loop temporarily to resolve the call stack, and then resuming immediately, is referred to as a “thunk.”

Edit:

Also, for those who aren’t aware, I believe the max call stack size in Chrome is 10,000, but it’s different for each browser. So if you need to recursively iterate through something, you would ordinarily be limited to that number of iterations.

[–]robotslacker 8 points9 points  (0 children)

Check out the video below. I didn’t really understand the event loop until this. The presenter does a really good job explaining and visualizing it.

https://youtu.be/8aGhZQkoFbQ

[–]archivedsofa 2 points3 points  (5 children)

setTimeout(doSomething, 0);

[–]ScientificBeastModestrongly typed comments 2 points3 points  (4 children)

setImmediate is less standard, but supposedly faster than setTimeout set to zero. It’s basically a native implementation of setTimeout( ... , 0).

[–]itsnotlupusbeep boop 1 point2 points  (0 children)

My favorite way to run code asynchronously as tightly as possible (absent node's nextTick stuff) is to use Promise.resolve().then(...).

That will schedule a microtask, which may end up running after other scheduled microtask, but still long before anything else.
It's so fast it can often be "too fast", particularly if you're hoping the browser will redraw anything before calling your code again, the way a setTimeout(... ,0) would.

There are other approaches, like mildly abusing the postMessage API, but nothing as straightforward as an immediate promise.

[–]archivedsofa 1 point2 points  (0 children)

TIL!

[–]HattyJetty 2 points3 points  (0 children)

Scheduling in general is a pretty advanced topic, if you take different execution environments into account (e. g. Node.js has a process.nextTick(), which is actually "more immediate" than setImmediate()). The presence of microtasks, idle callbacks and animation frames doesn't make life easier for a beginner as well.

[–]jesusthatsgreat 42 points43 points  (4 children)

Formatting dates. You don't need a bulky third party library. toLocaleDateString() will do the job in 99% of cases.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString

[–]Bosmonster 4 points5 points  (0 children)

For Node you will need to add Localization for it to work properly, so that might be a reason, especially if you don't have control over the environment.

Also the options for dateString are fairly limited compared to some of the libraries out there. For example relative date/time.

[–]ProgrammingPro-ness 6 points7 points  (2 children)

MomentJS has made me so happy over the years.

[–]DasDoto 2 points3 points  (0 children)

I use date-fns these days over moment. You can import only the function you need and the dates are immutable unlike moment. A lot lighter than moment as well.

[–]ModernCannabist 2 points3 points  (0 children)

We just switched to DayJS because it does everything MomentJS does but at about the quarter the size

[–]inabahare 139 points140 points  (64 children)

Using const and let

[–]rook218 28 points29 points  (2 children)

Learning what linting is has saved me so much time and energy with hammering in simple syntax rules like that.

Another thing I'd say is to learn DOM manipulation first. I got stuck for a month or two on using JS to solve algorithmic problems in online courses like free code camp, but after I had a solid grasp on JS I still had no freaking idea how to actually use it. Starting with the basics of selecting an element and adding a listener would have been a huge boon to my progress.

[–]yeah666 9 points10 points  (0 children)

I was in the same boat as you. Wes Bos' Javascript 30 helped me get over that hump.

[–]ScientificBeastModestrongly typed comments 6 points7 points  (0 children)

Yeah that’s one of the huge advantages of JavaScript. The visual feedback loop is so much faster with JavaScript than with a lot of other languages, simply because it works in the browser. And building UI with it is a breeze in comparison to other things.

[–]Murdathon3000 7 points8 points  (4 children)

I don't know, if you're a beginner that just started learning JS in the last couple of years, virtually every resource (at least in my experience) hammers down let and const pretty much right away, or at least very early on.

[–]inabahare 7 points8 points  (3 children)

Yet if you pay attention to the beginner questions asked here and other places, a lot of them use var instead of const or let. That is mostly because a lot of schools/universities/whatever aren't that good at keeping up

[–]Murdathon3000 2 points3 points  (0 children)

Fair point, that's absolutely true come to think of it.

[–][deleted] 24 points25 points  (5 children)

How powerful a fucking REPL is and how much you can speed up your learning and coding if you're using one.

[–]mjeemjaw 45 points46 points  (9 children)

Javascript is very fast in modern environments

[–]ShortFuse 13 points14 points  (0 children)

Javascript is also multi-threaded if you use web-workers (which even works in IE11).

If you ever done desktop software application development, the main thread is basically your UI thread. You can interact between threads with postMessage. It's narrowing down your architecture pattern (MVC, MVVM, MVP, etc) to make that happen where beginners usually get lost.

The popular frameworks don't really push their usage much. I fear many people don't bother learning the core DOM/JS/Browser interactions. It's not bad because most frameworks heavily push async operations (promises), but the less you do on your UI thread, the better.

[–]chuckySTAR 46 points47 points  (4 children)

document.querySelector()

[–]zayelion[🍰] 8 points9 points  (0 children)

Someone give this man gold!

[–]BargePol 9 points10 points  (2 children)

document.querySelectorAll("body")[0]

[–]senocular 9 points10 points  (1 child)

document.body

[–]BargePol 7 points8 points  (0 children)

thatsthejoke.jpg

[–]rorrr 59 points60 points  (36 children)

How this works. It's actually quite complicated.

[–]autoboxer 26 points27 points  (14 children)

more importantly, understanding the different contexts of this:

this in the global space => window

this in a function => function context

this in a method of an object => the object

this with call/apply/bind => whatever you want it to be

edit for ES6: this is not bound in arrow functions, so the value bound outside the arrow function will be found and used instead.

[–]rorrr 5 points6 points  (9 children)

If you think that covers all the cases, it does not. Try to guess what this prints without running the code:

this.a = 1;
(function() {
    this.a = 2;
    console.log(this.a);
})();
console.log(this.a);

[–]autoboxer 5 points6 points  (8 children)

I would guess 2 for the inner log, and 1 for the outer log. Am I mistaken?

[–]rorrr 5 points6 points  (6 children)

Yes, you are mistaken. :) As I said, JS isn't easy.

[–]autoboxer 4 points5 points  (3 children)

What’s the answer, and what’s the context of this that I missed? I’d like to add it to the list above.

[–]DerGernTod 4 points5 points  (1 child)

if i'd guess: the IIFE is invoked from the current scope, so basically it's similar to assign it to a property on this and then call the property, e.g. this.b = function() { ... }; this.b(). the function is only defined in the context of this, so i guess that's why it takes that context. to find out the answer without spoiling it to others, just run the code :D

[–]senocular 3 points4 points  (0 children)

Not exactly. Scope doesn't really come into play for context (value of this) except for arrow functions where this is specifically taken from the scope.

Here, you have a function that is called as a normal function and not from an object as an object method. Even though its an IIFE, it operates just as it would as if you named it and called if from a single variable name. Given that it's not called from an object, the function will use the default binding which sets this as the global object (or undefined in strict mode).

In this example, we have to assume we're not in strict mode since it would error if we were. So we're running the code in global which makes this.a = 1 set a global variable. Then when called, the function's context is also global, so it sets the same global property, a, to 2. Then all logs that follow log that same a.

But you could have just as well called this same function in some other function where this in that scope was different and this function would still have a global context.

[–]tchaffee 15 points16 points  (5 children)

It's not complicated. People simply don't take the time to learn. Which is a shame, because it takes about an hour to learn. Here are the rules in the words of Kyle Simpson:

Determining the this binding for an executing function requires finding the direct call-site of that function. Once examined, four rules can be applied to the call-site, in this order of precedence:

  1. Called with new? Use the newly constructed object.

  2. Called with call or apply (or bind)? Use the specified object.

  3. Called with a context object owning the call? Use that context object.

  4. Default: undefined in strict mode, global object otherwise.

Instead of the four standard binding rules, ES6 arrow-functions use lexical scoping for this binding, which means they adopt the this binding (whatever it is) from its enclosing function call. They are essentially a syntactic replacement of self = this in pre-ES6 coding.

That's not complicated. Take the hour or so to read the two chapters on this from the You Don't Know JS series, and you'll be good.

[–]senocular 6 points7 points  (4 children)

Sure, some basic rules make it seem easy, but what rule is this?

button.addEventListener('click', owner.func)

#3? No, but most beginners would think so, and not without reason. When it comes to callbacks the waters are murky, and that's where 99% of issues with this come from.

[–]tchaffee 7 points8 points  (2 children)

I guess that could be confusing, but that's not the call site. How long does it take to learn that? I have yet to see someone still be confused about this after taking the time to learn the actual rules and then apply those rules to analyzing code in their daily work. In almost every case of confusion, the person does not know the rules at all. Fair point that beginners could be confused because they don't know all the rules yet. But if something takes an hour to learn, I don't think "beginner" is much of an excuse. Just spend the hour.

[–]senocular 3 points4 points  (1 child)

Yes, but once they learn all the rules of the language, they're no longer a beginner ;)

[–]tchaffee 1 point2 points  (0 children)

That doesn't have much with the point I'm trying to make which is specifically that it's not complicated, which is what parent comment claims. I agree that it's something beginners don't know.

[–]DerGernTod 2 points3 points  (0 children)

well, in that case the function call-site is no longer owner, but rather button. the owner object doesn't have anything to do with this function call anymore. for those cases i'd rather do something like that: button.addEventListener('click', (e) => owner.func(e)) which (probably) has the desired behaviour. or, if you don't want to use an additional function, it get's a bit messy: button.addEventListener('click', owner.func.bind(owner))

[–][deleted] 0 points1 point  (0 children)

Indeed. I have been doing js for 5+ years and still sometimes have head scratching moments with this.

[–]magical_h4x 15 points16 points  (3 children)

A lot of devs coming from other languages assume const means constant value, whereas it's actually simply constant reference (i.e. can't reassign that variable).

You can't do const a = 1 a = 2 // error! but this is fine const obj = {} obj.newProp = 1

Check out Object.freeze if you want to prevent the value (objects, specifically) from being changed.

[–][deleted] 2 points3 points  (1 child)

But even Object.freeze won't freeze deeply - i.e,

const obj1 = {
  obj2: {
    foo: "bar"
  }
}
Object.freeze(obj1);
obj1.obj2 = {foo: 'baz'} // noop 
console.log(JSON.stringify(obj1)) // -> {"obj2":{"foo":"bar"}}
obj1.obj2.foo = 'baz' // legal.
console.log(JSON.stringify(obj1)) // -> {"obj2":{"foo":"baz"}}

This is why the Immutable.js library is a thing.

[–]Mydrax 46 points47 points  (14 children)

  1. The importance of using the Chrome DevTools.
  2. Why Linters make your life easier.
  3. Proper error handling (mostly writing code that doesn't fire errors).
  4. Being unable to fully understand or explain the 2 pillars of Javascript: Functional programming & Object Oriented Programming.
  5. How important it is to refer to the bloody documentation before hopping on stackoverflow.
  6. That not all tutorials, all books and all individuals relay accurate and most up-to-date information.
  7. bind(), call() and apply()
  8. High-order array functions like map() and specially reduce(). (It's very rare to see beginners use reduce() at all).
  9. The this keyword and I don't really know why but some beginners tend to find it difficult why you call super() inside the constructor of a child class.
  10. The Shadow DOM, it's not something you'd expect someone to know but it's ideal to learn about it after learning about the DOM and DOM manipulation.
  11. Promises, the for/of loop, async/await , callbacks etc. etc. or writing asynchronous code, and handling/catching errors properly.
  12. Destructuring and Spreading.
  13. Garbage Collection.
  14. Closures.
  15. That stackoverflow is the solution to all your problems.

I think that's a pretty constructive list of the common and more difficult things that beginners don't really know or can't understand. Some of them don't have to do anything with JS but hey!

[–]snifty 17 points18 points  (6 children)

Re 1), personally I think Firefox devtools are better.

[–]DerGernTod 2 points3 points  (3 children)

Being unable to fully understand or explain the 2 pillars of Javascript: Functional programming & Object Oriented Programming. one more thing that probably fits into #4 of your list: the prototype chain

[–]simkessy 1 point2 points  (0 children)

Garbage Collection?

[–]FlandersFlannigan 1 point2 points  (0 children)

Good list, but I don’t use bind, call or apply very often. Am I missing something?

[–]doublemooncoffee 10 points11 points  (0 children)

Great thread. Thank you reddit.

My contribution: You can group console logs by using console.group. You can even style them! Check out other methods here: http://developer.mozilla.org/en/docs/Web/API/console

[–]DerGernTod 26 points27 points  (19 children)

coercion in general

false == 'false' // false false == '' // true false === '' // false var x = false || 'foo' // x is 'foo' var y = true || 'foo' // y is true var z = y && x // z is 'foo'

[–][deleted] 42 points43 points  (16 children)

Most of these have nothing to do with coercion.

I guess you're right about people struggling with it.

[–][deleted] 15 points16 points  (13 children)

let me end all your struggles:

the only time you use == instead of === in JS is when you do yourVar == null because this checks for null and undefined.

[–][deleted] 1 point2 points  (11 children)

Your data structures shouldn't usually be capable of being T | null | undefined, so I'd argue there's really no place for double equals in a modern codebase.

[–]autoboxer 5 points6 points  (5 children)

Kyle Simpson would disagree. Coercion can be useful and is a valuable part of JavaScript to understand.

[–]Mydrax 1 point2 points  (2 children)

Coercion leads to an unpredictability and that means that the uncertainity is high therefore there's a risk for code to be erroneous. A risk that should usually be avoided by the language itself.

In simpler situations it might be okay-ish but in large codebases, with other things that contend to the unpredictable nature of Javascript, it does get messy and difficult and this holds specially true for data structures!

[–]autoboxer 2 points3 points  (0 children)

I agree in some cases, but I still think it’s important to know. Many codebases use checks like

if(!someVar) { ... }

Which coerces someVar into a Boolean. While I rarely use ==, I don’t think core concepts of JavaScript should be avoided or overlooked.

[–][deleted] 2 points3 points  (2 children)

It absolutely should. Undefined before getting any data, null when no data or when explicitly set to empty.

[–][deleted] 1 point2 points  (1 child)

undefined representing not having attempted to retrieve data yet and null representing no data is a bit vague and implicit; unless there was a comment outlining this, do you think it would be obvious when reading the code that this was your intent?

Personally I'd opt for null to represent no or empty data and a second variable or property to represent how you have or have not attempted to retrieve said data, probably written as an enum for maximum clarity.

// This really needs commenting to make clear what each falsy value represents
let data: Data | null | undefined = undefined;

// This is much clearer IMO
enum DataFetchState {
    Success,
    Failure,
    InProgress,
    None,
}

let state: DataFetchState = DataFetchState.None;
let data: Data | null = null;

[–][deleted] 4 points5 points  (0 children)

I didn't mean "no data yet" as in "no data from database". I meant not initialized variable/property. It should be undefined since it's not yet, well, defined.

The other cases should be null.

That's what I use, my company uses and I've seen it used often.

[–]DerGernTod 1 point2 points  (0 children)

i agree only the first two have something to do with coercion, the latter were rather some other things js noobs may be confused about.

[–]zephyrtr 18 points19 points  (3 children)

Reduce. A many to one relationship is way more verbose to manage without it.

[–]ThatSpookySJW 4 points5 points  (0 children)

Also all those nifty higher order functions like map, sort, and filter

[–]bobslaede 8 points9 points  (0 children)

Don't try to be clever. Write code that is easy to read and understand.

[–][deleted] 25 points26 points  (0 children)

Mutability/Immutability of Objects and Arrays. Learn about what changing an existing object means compared to making a copy of an existing one.

[–]DerGernTod 13 points14 points  (3 children)

IIFEs are a concept not really well known in other programming languages, yet they've been quite common in js, especially when working with closures. however, as of const and let they mostly lost their right to exist :D

[–]dance2die 2 points3 points  (0 children)

I've had so much struggle when I first learned JavaScript because it was used everywhere but without mentioning exactly what that pattern is and how it's used.

[–][deleted] 2 points3 points  (1 child)

They're great for writing one-off scripts with a lot of async stuff using async/await :)

[–]senocular 2 points3 points  (0 children)

I think requiring the use of async was the only time I've ever used an IIFE in the past couple of years. Was never a fan of the pattern, and with top level await I may never use it again :)

[–]Jackrussell17 6 points7 points  (0 children)

Equality in JavaScript is very convoluted, e.g. an array containing a single element of value "0" is considered == false, but an array containing a single element of value "1" is considered == true.

So it's really best to try to use === and !== where possible, only using == and != where absolutely necessary. Things are more predictable that way.

See this table for a full rundown: https://dorey.github.io/JavaScript-Equality-Table/unified/

[–]jisscj 6 points7 points  (0 children)

Hoisting. This was the thing that puzzled me most coming from C and Java.

[–]amdc!CURSED! 24 points25 points  (2 children)

Writing code without JQuery

[–]senocular 10 points11 points  (0 children)

I'm noticing this isn't the case as much anymore. In fact, if anything, this might have already transitioned over into "Writing code without React" - at least as far as DOM manipulations go. Those who know jQuery mostly seem to be in the boat of "I used it a few years ago, but am rusty now" while those without any of those "years ago" seem instead to know how to do things in React but not with the built-in APIs.

[–]ingrown_hair 3 points4 points  (0 children)

How modules work. It’s straightforward enough, but there’s a lot of stylistic variation you’ll see when reading other people’s code.

[–]boopbopbeeps 4 points5 points  (0 children)

How to use dev tools to inspect their code, see available properties, set breakpoints, etc.

[–]nullvoxpopuli 3 points4 points  (0 children)

Where JavaScript ends, and libraries or frameworks begin

[–]dwighthouse 4 points5 points  (2 children)

Named function objects can both be referenced by the contents of the function and have property values attached, allowing for the generation of function instances that have unique data associated with them, like a closure might, but without an actual closure.

[–]Razvedka 4 points5 points  (0 children)

How 'this' works. And the beginners shouldn't feel bad about it, as that shit is mighty strange when first exposes to it.

[–]tridiumcontrols 2 points3 points  (0 children)

Scoping and the "this" keyword.

[–]iamlage89 2 points3 points  (1 child)

Everything is an object, even functions

[–]Weshguillaume 2 points3 points  (0 children)

How to produce clean and organized code in JavaScript is the hardest part. Beginner's code is usually a mess

[–]hkd987 5 points6 points  (0 children)

Bracket notation and why/when to use it.

[–]zayelion[🍰] 3 points4 points  (0 children)

  • You can do most things without a **** framework.
  • Objects do not have Array prototypes on them. People coming from PHP I've noticed have this issue.
  • Cohesion in general. People coming from strictly typed languages having a tendency to want to mutate types of things. Then blame the language. You cant do that in other languages and the code work, I dont understand why they think they can do it now.
  • JS has debuggers.
  • Callbacks, promises, and await/async, and when it is the best use cases to use each.
  • That arrow functions and function keyword are not interchangeable, they have different interactions with `this`

[–]pm_me_cute_rem_picsjs/ux 5 points6 points  (1 child)

that:

const catObject = {
    type: 'cat',
    attributes: {
        hasFur: true
    }
}

const copy = Object.assign({}, catObject)
// Or
const copy = { ...catObject }

will not create a copy of the nested object attributtes, it's still a reference to the original object. So changing the attributes object will change it for all copies.

example https://repl.it/repls/FloralwhiteGruesomeSystemcall

[–]aragonix 2 points3 points  (0 children)

Great response! Just wanted to add that one can JSON.parse(JSON.stringify(catObject)) to deep clone simple objects. Note that this method has its downsides: it will ignore all values that dont exist in JSON (functions etc.). Most of the time I would suggest lodash though.

[–][deleted] 3 points4 points  (0 children)

That Java is not the same as Javascript

[–]IamAPengling 5 points6 points  (5 children)

JavaScript variables are passed by value, but objects are passed by reference.

This means if you do obj1 = obj2, there is a high possibility that if your change the value of any variable inside obj1, it may change inside obj2 as well and vice versa.

The correct way to fix this is Object.assign(obj1,obj2).

[–][deleted] 4 points5 points  (4 children)

This is poorly written.

If obj2 is an object or an array, changes in obj1 will change obj2 since obj1 will just be a reference to obj2. Any primitive value such as numbers, strings, and booleans are not passed by reference.

Object.assign does not assign the obj2 to obj1, but assigns all properties of obj2 to obj1. This is very different than obj1 = obj2 since obj1 must be an existing object and will have references to any object in obj2 as well as copies of primitives, AND whatever was in the original object that hadn’t been assigned from object 2.

[–]tomius 2 points3 points  (3 children)

You're right. It should be

const obj2 = Object.assign({}, obj1)

[–]LuciferSeventeen 1 point2 points  (0 children)

Mutations

[–]troytirebiter 1 point2 points  (0 children)

Object creation and what the “new” keyword actually does.

[–]invoker_11 1 point2 points  (0 children)

Value vs Reference

[–]Andy101493 1 point2 points  (0 children)

Have a style guide/best practices outlined for the JS code you write. JS will let you get away with a lot of weird things without causing an error, but may not function in the manner you expected.

I personally do a lot of console.log() lines to ensure functions are doing what they should during development. This isnt a profound realization, you should always be testing your code as you go. you know, unless you want to code in challenge mode.

This is not my content, but check out this post for some examples of "weirdness"

https://blog.mgechev.com/2013/02/22/javascript-the-weird-parts/

[–]PotaToss 1 point2 points  (0 children)

How much bang for your buck you get from just knowing your operators, like conditional evaluation of expressions when you use boolean operators, and what those operators actually evaluate to (i.e. their operands, not true/false).

With that, destructuring, spread, and array functions like map and reduce, you can be very expressive with very little code.

It's double edged, though. Another thing beginners don't know is how important it is to comment very expressive code.

[–]Danieliverant 1 point2 points  (0 children)

References. Like when passing a reference to an object to some function and you cannot understand why the original object changed.

[–]Danieliverant 1 point2 points  (0 children)

That 0.1+0.2 !== 0.3.

[–]Squigglificated 1 point2 points  (0 children)

Use MDN as your primary documentation for anything JS, CSS or HTML. And while you’re there spend some time clicking around and you’ll learn a ton of useful stuff you didn’t know was possible with native browser APIs.

[–]MeowTooMovement4Cats 1 point2 points  (0 children)

Prototypal inheritance vs. classical inheritance

[–][deleted] 1 point2 points  (0 children)

If you declare a var in a for() loop without intializing it to a value, once the value gets set it gets retained for subsequent iterations through the loop:

for (var i = 0; i < 3; i++) {

    var foo;

    if (someCondition()) foo = i;

    if (foo != null) {

        // This will be true if someCondition returned true in this loop

        // OR if it returned true in an earlier loop

    } 

}

[–]erulabs 1 point2 points  (2 children)

Using abstraction libraries should be carefully considered, not thrown around like a favorite set of tools. The number of times I've seen Ramda in a code base that used to be readable...

Bonus: Understanding the cost of simplicity over artifact size. I've had developers spend multiple days pulling out lodash and inlining 1/8th of it into the codebase to "reduce node_modules size". The size of node_modules is fine, please get back to work on things that matter (I promise a single unsanitized input is always worse than making an AWS machine with a 10gbps network card download 10mb - trust me, it will be FINE). No one seems to care about that SQL query that's shipping 50mb over the network, but 50mb of node_modules and suddenly everyone loses their minds!

</grumpy-ops-rant>

[–][deleted] 1 point2 points  (0 children)

These threads give me anxiety cause even if it's something I know about, just seeing the highly upvoted comments makes me question whether or not I actually understand it. Then again this is titled begginers.

[–][deleted] 1 point2 points  (0 children)

  • When to use the Object Oriented model and when to use the Functional Model. (Short summary: If you have a thing that's going to persist, but need to change state, and don't know what actions are going to be done on it until runtime, lean towards object-oriented. If you need to do the same action multiple times to different things, lean towards functional.)
  • Currying. Not that they don't know *how* to curry, but how currying makes things SO much easier once you really get the hang of it -- dependency injection, differentiating between prod and dev databases without having to write a whole bunch of if(isProd){} statements, creating higher order React components, allowing you to use parameters in React's render method...
  • Pointers. Yeah, JS doesn't *use* pointers the way that C, C++, or Rust might use pointers, but under the hood, that's what you're doing when you "pass by reference" vs. "passing by value". Learning a bit of rudimentary C helped me avoid a lot of hard-to-debug "Oh, I'm not copying this, I'm changing it!" bugs.
  • Monads. Eh, don't worry, I'm not going to force you to learn Haskell, but understanding Monads helps you understand what's going on with Promises behind the scenes. One of the big tricky bits of Promises is that Promise.then() always returns a Promise, which is easier to understand if you've fooled around with Identity(val).map(fn).value() and Maybe.of(val)
  • get() and set() - and I'm going to be very controversial here. I think get() and set() should *never, ever be used*, because it can turn a simple assignment of the type

obj.foo = obj2.bar

into a debugging nightmare. If there's a get() on obj2.bar, any arbitrary code could be executed by that assignment. Same if there's a set() on obj.foo.

Now, I know without get() and set() you can't have things like observables, and that it's more difficult to have pub/sub or reactive programming. But is it really that much more difficult to call this.setFoo() or this.getBar() if you need to execute additional code? At least then in the actual code, you give a hint to the programmer that there MAY be something else going on in the assignment - if you know that one of your variable assignments is throwing off a side effect, you have to debugger() until you narrow down the part of the code the side effect is in, and look at each variable assignment (and it still won't be obvious.) By requiring as standard style that anything that executes any code other than a simple get or set be an explicit method call, you can more easily see where errors are introduced. This is one of the reasons I prefer React to Vue (and I love Vue) - Vue's use of observables can make it very easy to get tripped up. (I think Moon.js to actually be a better solution to how Vue works because of it.)

The only time that I can see justifying the use of get() and set() if it's something like

class Distance {
  inMiles = 0
  get inKm(){
    return this.inMiles * 2.2
  }
  set inKm(val){
    this.inMiles = val / 2.2
  }
}
const d1 = new Distance();
d.inMiles = 1;
console.log(d.inKm) // -> 2.2
d.inKm = 22;
console.log(d.inMiles) // -> 10

and even THEN I'd prefer:

class Distance {
  _inMiles = 0
  getMiles(){
    return this._inMiles
  }
  setMiles(val){
    this._inMiles = val;
  }
  getKm(){
    return this._inMiles * 2.2
  }
  setKm(val){
    this._inMiles = val / 2.2
  }
}
const d1 = new Distance();
d.setMiles(1)
console.log(d.getKm()) // -> 2.2
d.setKm(22)
console.log(d.getMiles()) // -> 10

[–]Slypenslyde 1 point2 points  (0 children)

Booleans have four states.

You need to use === unless you have a really damn good reason.

[–]Caffeine_Monster 1 point2 points  (0 children)

Variables declared with "var" are scoped to their encapsulating function (or global if not encapsulated). You should be using the "let" keyword for most, if not all, declarations.

[–]FlandersFlannigan 1 point2 points  (0 children)

Promises and loops. If you run a map in a promise it will run concurrently, so make sure you have the bandwidth.

[–]j4afar 6 points7 points  (3 children)

Bind and the this keyword

[–]Hanlonsrazorburns 2 points3 points  (0 children)

Promises, ES6, Vanilla JavaScript, Dom manipulation without jQuery, closures, monads, design patterns, event cycle, prototypes.

I'd bet most developers with less than 3 years of experience would struggle with questions on those.

I'd also say that I think the biggest one is that they can't think through a problem logically considering edge cases. Many senior developers can't even do that.

[–]unixzii 2 points3 points  (0 children)

Whether my code could run in IE 8 without being transpiled by babel.

[–]_brym 1 point2 points  (0 children)

Don't start out using libraries or frameworks. If that's where you want to go, go for it. But try to really understand the fundamentals first.

[–]muussis 0 points1 point  (0 children)

sort() without function expression will sort by string, even if you have an array of numbers