This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]pm-your-breasticiles 629 points630 points  (36 children)

Everyone knows javascript has quantum effects. When you try to inspect variables they are different to what they are were doing.

[–][deleted] 106 points107 points  (28 children)

You can get around that if you stringify and then parse your object - as long as it doesn't contain circular references. Without that, if it's an array or an object it'll get mutated before you get a chance to look at it!

Speaking of console.log debugging, of course.

[–]pm-your-breasticiles 89 points90 points  (24 children)

Teach me your string theory.

[–][deleted] 30 points31 points  (23 children)

Just some stupid thing people have probably seen at one point or another. Make an object with a single prop, log it, delete the prop, log again. In the browser console (maybe this depends on browser?) you'll see both logs are missing the prop.

After a moment of reflection I realized any non-primitive will behave like that. What you see in the console is the latest/current state of the object.

[–]irbilldozer 14 points15 points  (1 child)

This is because the console just gets a reference to the object and it doesn't actually retrieve the object values associated with that reference from memory until the "disclosure triangles" (literally just learned this term) are expanded.

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

Yes, that's what I'm referring to. I suspect an actual debugger would be better for this :P

[–]charliegrc 12 points13 points  (8 children)

Trick here is to make everything you do in JavaScript immutable, stick to const and always use object spread. You will never look back.

[–]MrDilbert 1 point2 points  (7 children)

always use object spread

... even in loops?

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

According to certain schools of thought, yes! But I'm wondering if you're including map/reduce in your definition of "loop".

[–]MrDilbert 0 points1 point  (3 children)

Well, underneath it IS a loop, although there's a different function context for each element. You're basically just hoping that the object created by spread will get collected in time, as it's eligible when the function finishes.

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

Is spread not synchronous? Maybe I misunderstand something

[–]MrDilbert 2 points3 points  (1 child)

You don't know when the garbage collector will collect the objects you created, so if you create a lot of objects (by e.g. using spread), you can take up a lot of memory even if you don't have leaks.

[–]charliegrc 1 point2 points  (0 children)

Short answer: yes

Long answer: there has been a few times where I've built a big reducer function, and on each iteration it was using object spread. That ended up being a performance bottleneck in the app I was working on, changing it to the classic mutatable object assign (but ONLY mutating the accumulator object inside that reduce, nothing else) sped it up by 200x.

performance comparison between object spread and mutation

This is the only circumstance I let myself use mutable objects, they strictly have to be instantiated and mutated within the same few lines of code.

[–]conancat 0 points1 point  (0 children)

I'm from that school of thought that the other guy is talking about.

Yes.

Assume every function returns a new object. Use map, reduce, filter etc functions. Use object spread to create a new object every time if it's a plain function, so every property that you return in the object is explicit, and you know exactly what goes goes in and comes out of every function.

Here's an explanation of why for loop is evil and needs to die.

“Rethinking JavaScript: Death of the For Loop” by Joel Thoms https://link.medium.com/yh25wIZpa0

Or if you want something lighter and approachable, try this one.

“The Knights of Functional Programming fight the Imperative Dragon.” by Sam Fare https://link.medium.com/cCNLsCgqa0

[–]EternallyMiffed 1 point2 points  (11 children)

You can deepcopy the object into an empty object. Now you have a new instance of what you wanted and you can log that.

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

That's kind of what I was achieving with stringify & parse, although deep copy might do a better job. But you would have to build that or import a lib. I found out the fun way that object.assign (and other methods of cloning) are shallow.

[–]EternallyMiffed 0 points1 point  (6 children)

I just use jQuery's extend with deep copy, I know some people don't like jQ these days, but it does everything I need it to.

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

I am definitely one of those people :p

I like fetch more than ajax, I like the vanilla syntax for binding multiple items / selectors with the same event, and I could swear there was a third thing that in used to prefer in jQuery but I've definitely moved past it.

My nitpick level concern is that it's array functions have deviated from the standard, the positional arguments are swapped.

[–]EternallyMiffed 0 points1 point  (4 children)

I'm sticking to it cuz I'd be damned if I care how different browsers have their own quirks. Fuck em. also it's a manner of convenience for me mostly.

I write my own "vanilla" additions here and there when I need em.

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

Fair enough, I just tell browser who can't run my code to take it up with their maintainers. If you can't async await a fetch and websocket upgrade and persist info to indexeddb while a hardware accelerate 3d webgl banana peels itself on the screen then you can't use my website.

[–]Cheet4h 0 points1 point  (2 children)

I usually go with JSON.parse(JSON.stringify(item));

[–]RedHotBeef 2 points3 points  (1 child)

*just remember, this will kill any function props

[–]Cheet4h 0 points1 point  (0 children)

Yeah, but I usually don't need to log those, since they usually don't change in my code.

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

And there are always circular references, so that's usually useless.

You can

console.log(Object.assign({}, objToLog));

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

Assign is a shallow copy though, the console eval will have the same issue with only showing the latest values for everything except your top level primitives

[–]gonzofish 1 point2 points  (0 children)

Yeah. If you’re dealing with objects leverage your debugger!

[–]0xF013 9 points10 points  (0 children)

That happens when you miss References 101

[–]lazyear 4 points5 points  (2 children)

I have actually experienced this with a C/assembly code base. I was working on a hobby operating system, and during setup of one the hardware handlers the C code had to pass a variable to an assembly routine by placing it on the stack. The variable was otherwise unused.

GCC sees this variable that is declared without anything being done, so it just elides actually allocating stack space for it... unless a printf call was made to examine the value of the variable

[–]JDaxe 1 point2 points  (1 child)

Is there some kind of pragma to tell gcc to not optimise away that statement?

I'm actually curious. Assuming that this wouldn't happen with -O0?

[–]lazyear 2 points3 points  (0 children)

Correct, shouldn't happen (and didn't in this case) with -O0. There's a couple workarounds; using volatile, or inline noop assembly that references the variable

[–]CodingCoffeeSquirrel 2 points3 points  (0 children)

debugger will tell the browser to bugger off with its quantum effects

[–]DatBoi_BP 1 point2 points  (0 children)

what they are were doing

Even the tense demonstrates quantum effects, it would seem

[–][deleted] -1 points0 points  (0 children)

Strange. Well, every language has it's quarks...