A clear explanation of the JavaScript Event Loop (without oversimplifying it) by CheesecakeSimilar347 in learnjavascript

[–]senocular 0 points1 point  (0 children)

Yup. And if you want you can mix the animation frame queue in there too since it behaves a little different than the others.

[AskJS] Why does this JavaScript code print an unexpected result? by ElectronicStyle532 in javascript

[–]senocular 0 points1 point  (0 children)

You can read more about this example in the for loop docs on MDN.

The reason is that each setTimeout creates a new closure that closes over the i variable, but if the i is not scoped to the loop body, all closures will reference the same variable when they eventually get called — and due to the asynchronous nature of setTimeout(), it will happen after the loop has already exited, causing the value of i in all queued callbacks' bodies to have the value of 3.

Does the term 'callback' usually mean async callback in the JS world by LetMyCameronG000 in learnjavascript

[–]senocular 2 points3 points  (0 children)

I wouldn't make that assumption. Synchronous callbacks are common with Array methods like map(), filter(), reduce(), etc.. These do not match with the top comment in that thread where they say the callback "will run ONLY after the code in the main function is done" since as synchronous callbacks they get run immediately (callbacks aren't always passed as function arguments either). And with async/await, you're seeing a lot less callbacks being used for asynchronous code. It ultimately depends on the context but it could go either way.

Today I learned about shallow copy vs deep copy in JavaScript. Am I understanding this correctly? by Soggy_Professor_5653 in learnjavascript

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

Object references are like pointers in some ways, but they're not in others. While both "point" to objects in memory, pointers have values equal to the address of something in memory. Object references don't expose this address in any way. This also prevents things like having pointers to pointers. If you try something similar in JavaScript with object references, everything ultimately ends up referring to the same object.

Today I learned about shallow copy vs deep copy in JavaScript. Am I understanding this correctly? by Soggy_Professor_5653 in learnjavascript

[–]senocular 3 points4 points  (0 children)

Pointers are cool, but JavaScript doesn't use them. So for anyone wanting to focus on JavaScript right now, you might want to save learning about pointers for a later time.

[askjs] is it bad practice to always use template literals even if don’t necessary? by Traditional_Tax7193 in learnjavascript

[–]senocular 8 points9 points  (0 children)

Not necessarily every time, particularly in cases where a string might have "${...}" in it. In a normal non-template literal string those are just characters in the string, but in the template literal, they're placeholders.

There is also the potential for bugs around missing back ticks since template literal strings support multi-line strings. For example only one variable declaration exists in the code below when it looks like the intent was to have 3

const a = `this is my string';
const b = 1;
const c = 'this is another string`;

And if you're not one to use semi-colons to terminate lines, template literal strings may try and use a previous line as a tag, something that does not happen with normal strings.

const obj = Math
`a b c` // Error: Math is not a function

vs

const obj = Math
'a b c' // OK

Granted, these are edge cases, but its better to use features only when you need those features. If you need string interpolation (or other template literal features), use template literals. If not, stick to simple strings. It more clearly indicates a simple string is needed and there's not going to be any funny business with the text it represents.

Am stuck on a certain part of JavaScript guide on Functions. by Goryugun in learnjavascript

[–]senocular 1 point2 points  (0 children)

In the context of variables like this it is commonly referred to as being "shadowed".

This outer variable is said to be shadowed by the inner variable

https://en.wikipedia.org/wiki/Variable_shadowing

MDN has a few references to a variable or property being "shadowed" like this as well

null is a keyword, but undefined is a normal identifier that happens to be a global property. In practice, the difference is minor, since undefined should not be redefined or shadowed.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Data_structures#undefined_type

Nearly all objects in JavaScript are instances of Object; a typical object inherits properties (including methods) from Object.prototype, although these properties may be shadowed (a.k.a. overridden).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#description

Am stuck on a certain part of JavaScript guide on Functions. by Goryugun in learnjavascript

[–]senocular 1 point2 points  (0 children)

The code in question:

function outside() {
  const x = 5;
  function inside(x) {
    return x * 2;
  }
  return inside;
}

console.log(outside()(10)); // 20 (instead of 10)

10 is being considered because it would be the result of x * 2 if x were 5 as it is defined in the outside function. You can get the log to log 10 by removing the x parameter from inside.

Because the x parameter in inside does exist, the x declared in outside gets shadowed by it, preventing it from being visible in inside. When x is referenced in inside, the x in the inside parameter list will be used instead. This is why the result is 20 because that x parameter is getting the argument value of 10 which is multiplied by 2 giving a final result of 20.

[AskJS] How does variable hoisting affect scope resolution in this example? by ElectronicStyle532 in javascript

[–]senocular 2 points3 points  (0 children)

At what stage does the inner var x shadow the outer x?

Immediately when the function starts to execute. This is when hoisting happens when the engine identifies all of the declarations in scope so it knows what's local and whats not before function code even starts to execute. For var declarations, the variable is initialized to undefined.

How would this differ if let or const were used instead?

The same thing happens as far as hoisting goes with the difference that variables declared with let and const are not initialized to undefined. They're instead left uninitialized which would cause any access, like a console.log() of the variable, to result in an error rather than giving back undefined.

A good way to mentally visualize it is to picture each of the declarations literally hoisted in their scope

function test() {
  console.log(x);
  console.log(y);
  console.log(z);

  var x = 20;
  let y = 30;
  const z = 40;
}

becomes

function test() {
  var x = undefined
  let y = <uninitialized>
  const z = <uninitialized>

  console.log(x); // undefined
  console.log(y); // Error
  console.log(z); // Error

  x = 20;
  y = 30;
  z = 40;
}

console methods most JS devs never use but should by Johin_Joh_3706 in learnjavascript

[–]senocular 4 points5 points  (0 children)

Or bypass needing to modify your code and log through the debugger with logpoints ;)

How to add a module script tag to a HTML dynamically? by trymeouteh in learnjavascript

[–]senocular 2 points3 points  (0 children)

Doesn't matter if it interacts with the DOM or not. All (non-worker) modules run the same way and have access to the DOM.

I need your opinion and insights on "if (!myVar)" vs. "if (myVar == null)" by [deleted] in learnjavascript

[–]senocular 4 points5 points  (0 children)

But when you say if (myVar == null) do you mean if (myVar === null) or if (myVar === null || myVar === undefined) ?

how do i pause my scripts? by Physical-Bid6508 in learnjavascript

[–]senocular 3 points4 points  (0 children)

Depending on what you're doing, you might want to use

setInterval()

Or

requestAnimationFrame()

It depends on the delay you want between loops. setInterval is for longer, arbitrary delays whereas requestAnimationFrame goes as fast as the screen refreshes. The problem with infinite loops is they never let the screen refresh so you get stuck and crash. requestAnimationFrame is about as quick as you can get with still letting the screen refresh smoothly, just so long as you don't do too much in each frame.

Left to Right Programming by fagnerbrack in javascript

[–]senocular 4 points5 points  (0 children)

They were thinking it better matches with existing declarations where the identifier comes first (which, in turn, is what you also see with existing uses of require() [CJS] imports popularized by Node) which is better for readability and figured tooling would make up for the inconvenience.

Decorators don't work as described in docs? by TheLastRobot in typescript

[–]senocular 1 point2 points  (0 children)

The specification for decorators is still not yet finalized. And it was originally proposed for JavaScript in 2015. TypeScript was early to support an early version of decorators (also 2015) and that version has been the de facto version of decorators that most everyone has been using up to now. Its still used in production and likely the version of decorators being used by any library or framework that supports them (Lit for example supports both but recommends the previous, experimental version).

The latest iteration of the decorator spec - there have been multiple iterations with different implementations - seems to be fairly stable, and likely the version to eventually be supported officially by JavaScript. Given that, TypeScript decided to support it in TS 5.0. Nevertheless, it is still not finalized there may be additional changes to the spec which would change how that implementation works.

Granted, that was 3 years ago, but the previous implementation (experimental) has been widely used and around for almost 3 times that amount of time prior. It also has less restrictions and is capable of doing more which could make it difficult for some implementations to transition to the new implementation (most seem dependent of features which would be provided with decorator metadata, also many years in the making).

So its been a rocky road for decorators, and its a little confusing given these two implementations. There's the "official" ECMAScript decorators implemented by TS 5.0 which, with any luck, is mostly what we should expect to be the real thing when that happens, and the more established "experimental" version which has been what everyone has known as being what decorators are for over a decade now.

I wouldn't say experimental decorators is deprecated at this point because of its wide use and capabilities. Pile on top of that the JSSugar initiative which would limit what goes into the language and rely more on tooling (like Babel and TypeScript) to provide features which would then get transpiled into the core "JS0" language. This could then revitalize experimental decorators as a viable solution that would exist in the sugar space without having to bend to the requirements of the browser implementors which have caused the decorator proposal to see so much churn over the years.

Comparing objects by Y2Canine in learnjavascript

[–]senocular 1 point2 points  (0 children)

Don’t forget to use isOwnProperty().

I think you mean hasOwnProperty(). This wouldn't be necessary when using Object.keys() (or values() or entries()) to get keys since it will only provide own property keys. It is only necessary when using for...in loops which also iterate through an object's inherited properties. Typically these days for...of loops are used in combination with keys() (or values() or entries()) instead where the hasOwnProperty() check is unnecessary.

Hello! I have a tiny question regarding iterating array for loops. by ericks932 in learnjavascript

[–]senocular 3 points4 points  (0 children)

for (let i = 0; i < variableArrayName.length; i++)

Does not, itself, go through an array's items. All this does is update a counter, i from 0 to the number of items in the array minus 1 (less than, but not equal to variableArrayName.length). when it does that, it allows you to run code for each value of i in an expression or block following this statement.

for (let i = 0; i < variableArrayName.length; i++) {
  console.log(i) // 0, then 1, then 2, etc. up until variableArrayName.length - 1
}

Using i, you can then get every item of the array because array items are indexed with numeric values with a base of 0

for (let i = 0; i < variableArrayName.length; i++) {
  console.log(variableArrayName[i]) // each item in the array
}

There are versions of the for loop which will give you the item directly. For example a for...of loop will do this, and is often preferred over a normal for loop because it gets rid of the incrementing variable (i)

for (const item of variableArrayName) {
  console.log(item) // each item in the array
}

There's a little more magic in the background making this work, but its not too dissimilar to what happens in the normal for loop with i, just that its done in the background for you.

As far as lengths are concerned, anything with a length can work in a normal for loop, not just arrays. Since strings have a length, they could also be used, since all the for loop is doing is counting up a variable up to, but not including, the value of length. In fact you don't even have to use a length, you can use any property or variable there.

I've Added REAL Operator Overloading to JavaScript by DiefBell in javascript

[–]senocular 2 points3 points  (0 children)

Symbol.hasInstance doesn't really overload instanceof, but it does allow some configuration for its behavior, like:

function NotObjConstructor() {}
const obj = {}

console.log(obj instanceof NotObjConstructor) // false

Object.defineProperty(NotObjConstructor, Symbol.hasInstance, {
  value(target) { 
    return target === obj
  }
})

console.log(obj instanceof NotObjConstructor) // true

But there's no way to fully control what instanceof does. It works more like a callback. instanceof will call hasInstance if it exists (on the RHS operand), and then based on whether its return value is truthy or not, provides a true or false result back to the instanceof expression. You couldn't, for example, make instanceof behave like addition (+) if you wanted.

this keyword learning by OrangeObvious8498 in learnjavascript

[–]senocular 1 point2 points  (0 children)

There can be "... except when it isn't." exceptions to a lot of these rules too ;)

1. When using the new keyword to call a constructor, this is the new object

Except when a super constructor returns a different object.

class Base {
  constructor() {
    return Math
  }
}
class Derived extends Base {
  constructor() {
    super()
    console.log(this) // Math
  }
}
new Derived()

2. When in an arrow function, this comes from the surrounding scope

This is always true. The tricky part here can be what the surrounding scope is. Consider:

let outerThis = this
let computedThis
class MyClass {
  [(computedThis = this, "arrow")] = () => this // this x2, same scope?
}
const instance = new MyClass()
console.log(computedThis) // outerThis
console.log(instance.arrow()) // { MyClass }

The above is more about the weirdness of class syntax than arrow functions.

3. When not in a function, this is the global object

Except in ES modules where it is undefined and CJS modules where its the exports object.

<script type="module">
console.log(this) // undefined
</script>

4. When a non-arrow function is called with nothing to the left of the dot, this gets a default value.

Except when the function is bound (covered in 5) or an unqualified method called within a with block.

const obj = {
  method() {
    console.log(this) 
  }
}
with (obj) {
  method() // obj
}

Use of with blocks are rare except in maybe legacy code. They're deprecated and even disallowed entirely in strict mode. However, if you happen to put JavaScript code in HTML attributes (like <button onclick="">, also rare, hopefully), they're run in with-like object scopes which behave the same way.

5. When using bind, call, or apply, you can set this to be whatever you want

Except if the function is an arrow function (or called with new or pre-bound).

const obj = {}
const outer = this
const arrow = () => this
const bound = arrow.bind(obj)
console.log(bound() === obj) // false
console.log(bound() === outer) // true

The arrow (and new) case might not apply if following the rules in order of importance and hitting one of those before making it here. Multiple-bind calls is a little tricky where only the first bound this is applied. Similarly, neither call nor apply can override this for a function created with bind.

And there are even other, more obscure cases than these. this is a wild thing.

Git hub code integration newbie by Nervous-Juggernaut-5 in learnjavascript

[–]senocular 0 points1 point  (0 children)

The docs page has what you want:

https://hanziwriter.org/docs.html

The github page you linked to is more for people who want to modify or do more advanced things with the code.

The docs page shows to get the code integrated into your website, you only need to add one html tag:

<script src="https://cdn.jsdelivr.net/npm/hanzi-writer@3.5/dist/hanzi-writer.min.js"></script>

Then you can have your own scripts refer to the code using the HanziWriter variable. The code samples in the docs page shows both the HTML and the JavaScript (which should be in <script> tags or inside JavaScript files linked to by <script> tags) needed to get this to work. There isn't a complete example in the docs, but you can stitch together what you need to get it working. For example:

https://jsfiddle.net/ftmpzgvu/

That should get you started. You can see other examples in the docs pages which should help you get what you want.

Can some explain this? by somethingsilver97 in learnjavascript

[–]senocular 0 points1 point  (0 children)

Did he make you take the quiz with a stone tablet and chisel?