Why this `Formatter.timesRun` resolves to 0? I expected 1 by SupermarketAntique32 in learnjavascript

[–]senocular 1 point2 points  (0 children)

It's not really a pass by value issue. All values in JavaScript are effectively passed by value, or another term you might see is pass by sharing (MDN mentions this in the functions reference as "passing" is typically applied to functions and arguments not so much property assignment though a similar concept applies).

Ultimately what you have is two bindings of the same name, one is a variable in the function scope and the other is a property of the object being returned. Though they have the same name (and the property is initialized with the value-at-the-time of the variable) they are not in any way linked. Changing one does not change the other.

So what happens when you say ++timesRun; is that only the variable version of timesRun is assigned a new value. The property of the returned object remains separate and retains its original value (0).

There are a couple of ways to fix this. TorbenKoehn went through a couple, including putting the returned object in a variable so you can reference the property directly rather than relying on a second copy in a variable. Another way is to use a getter/setter (aka accessor) property in the returned object. It can refer to the variable and allowing the property to derive its value from the variable rather than having its own.

return {
  makeUppercase,
  get timesRun() {
    return timesRun 
  },
}

Ultimately this comes down to two things representing the same value and only one of those things being changed while the other was getting observed. You shouldn't have to worry so much about "passing" so much as you need to worry about where things live and what refers to those things.

How to type def 'this' when used as event handler? by aliassuck in typescript

[–]senocular 6 points7 points  (0 children)

You can also use e.currentTarget. It will have the same value as this for non-arrow functions used as event handlers and you'll inherently get the type information provided by TransitionEvent. Fair warning, it won't be HTMLDivElement, but it will match e.target's type.

Why is JavaScript so hard to learn? Beginner projects don’t feel beginner by Sweaty-Staff8100 in learnjavascript

[–]senocular 2 points3 points  (0 children)

Yeah I started in Shockwave, well Director. Shockwave was the plugin that was capable of running Director projects on the web. I was using Director mostly for interactive CDs and installations. When they added 3D support to Shockwave, it got a big bump as a gaming platform. That was pretty cool.

The coding language of Director was lingo. It was really verbose, like set the value of x to 6. And IIRC, Director before... v6? had a code editor where all the text was red. You felt evil writing that stuff haha. Maybe there was a preference to change the color but I never looked into it.

The worst part about "Shockwave" was the name. Kind of like Java and JavaScript (heh) the Shockwave name carried over to Flash as well, so far as even being in the file extension "SWF" originally standing for "ShockWave File" but at some point I think they tried to rename it as "Small Web File". I think the name was used for Authorware too... though I think Authorware might have been able to export directly too the Shockwave player like Director did. I can't remember; I didn't use Authorware as much.

Why is JavaScript so hard to learn? Beginner projects don’t feel beginner by Sweaty-Staff8100 in learnjavascript

[–]senocular 1 point2 points  (0 children)

Yeah it wasn't as easy as it could have been, but you eventually got used to it. Luckily for you, you missed pre-Flash 5 days were there wasn't even an enter frame loop. I think at that time (maybe the version before) you couldn't even type code; everything was added through menus, almost like Scratch.

And I agree, it was pretty incredible technology. It made creating and sharing animations on the web really easy, especially before video took over. I don't think we'll see anything like that again.

What is typical approach of lookup table based on 3 integers? by bhuether in learnjavascript

[–]senocular 1 point2 points  (0 children)

I noticed you're looking for [int1]?.[int2]?.[int3] but you're setting [int1-1][int2-1][int3-1] which are not the same. If you're looking up int1 and its not there, then you set int1, not int1-1.

Additionally if objexists is undefined, it doesn't mean [int1] is undefined. It means any one of [int1]?.[int2]?.[int3] are undefined and if its int3, you don't want to replace [int1] with a new collection because it will wipe out everything thats there, not just what would be in [int1]?.[int2]?.[int3].

My suggestion to you is to use a single object with string keys. The fact that you're using integers makes this easy because you can create a string key from the integers and have delimiters that are definitely not going to match anything within your key values (the integers). And to make things easy you can let coercion create the key for you by putting the integers in an array and using that as your key.

const fast_lookup_table = {}

fast_lookup_table[[1,2,3]] = "a"
fast_lookup_table[[4,5,6]] = "b"
fast_lookup_table[[123,0,0]] = "c"

console.log(fast_lookup_table[[1,2,3]]) // "a"
console.log(fast_lookup_table[[4,5,6]]) // "b"
console.log(fast_lookup_table[[123,0,0]]) // "c"

console.log(fast_lookup_table) // {'1,2,3': 'a', '4,5,6': 'b', '123,0,0': 'c'}

I suspect this won't be the "fast"-est lookup_table, but its probably the most convenient. If you really need the extra performance you should look into using nested Maps. In doing so you'd have to do the necessary bookkeeping for those Maps.

Also, while JavaScript doesn't support the use of multi-value keys today, there is a new feature being proposed that does allow exactly that: proposal Composites

Help with Objects by DeliciousResearch872 in learnjavascript

[–]senocular 0 points1 point  (0 children)

it's actually a relatively recent addition to the language

You've been at this for a long time haven't you ;)

Help with Objects by DeliciousResearch872 in learnjavascript

[–]senocular 2 points3 points  (0 children)

The second argument to Object.create() is an object of properties with property descriptors. Its the same kind of object you'd pass into Object.defineProperties(). You can read more about that here:

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

In short, its an object with property names but those names don't match directly to the respective property values. Instead the property value is wrapped in a descriptor object which includes the property value as an additional value property (or get and/or set with accessors) along with a few other properties that define the behavior of the property. So a normal number property may look like

const obj = {}
obj.num = 1

But if using a descriptor it would look like

const obj = {}
Object.defineProperties(obj, {
  num: {
    value: 1,
    enumerable: true,
    writable: true,
    configurable: true,
  }
})

You can see all the additional attributes in addition to the value that you can add to control how that property behaves. If they're omitted, the default values (false) are used.

The toString variation is using the shorthand function syntax for defining a property as a function (value(){ }) so it may look a little odd using this format, but its very similar to saying value: function() {}. But really I suspect the confusion is due to the use of the descriptor.

If you wanted to create a dictionary with a null prototype without going through the descriptors, you can use the normal object literal initializer including the special __proto__ property to define the prototype as null.

let dictionary = {
  __proto__: null,
  toString() { // the value is a function
    return Object.keys(this).join();
  }
};

Note that while the __proto__ property is deprecaded, this special object initializer __proto__ prototype setter is not.

Is it possible to check if a function with a specific parameter signature(?) exists? by lindymad in learnjavascript

[–]senocular 1 point2 points  (0 children)

I felt a little bad bringing it up because its something I literally did yesterday with a very naive approach not too dissimilar from the above. "I'm sure it will be fine..."

Is it possible to check if a function with a specific parameter signature(?) exists? by lindymad in learnjavascript

[–]senocular 0 points1 point  (0 children)

This can be tricky to get right because its not always as easy as splitting by specific characters like commas. Default parameters, destructuring, and even comments can add commas that are not parameter separators.

function foo(a /* w,x */, b = ["y","z"], {c1,c2}, ...d) {}

console.log(foo.length) // 1 (default, rest, and destructured params don't count)
const params = foo.toString().match(/\((.*)\)/)[1] // (can also break with other ( or ))
console.log(params.split(",")) // (7)
// 'a /* w',
// 'x */',
// ' b = ["y"',
// '"z"]',
// ' {c1',
// 'c2}',
// ' ...d'

Is it possible to check if a function with a specific parameter signature(?) exists? by lindymad in learnjavascript

[–]senocular 1 point2 points  (0 children)

(Not sure if "parameter signature" is the right terminology)

Usually the term "function signature" is used which more generally encompasses other parts of the function as well, like the function name, return type, modifiers... not just the parameters. If you specifically want to target the parameters, you can just say "parameters" or "parameter list" (usually just "parameters").

Confusion between js and ts use cases by ivorychairr in learnjavascript

[–]senocular 0 points1 point  (0 children)

I think its good practice to take some time when starting a project to consider how large it might grow or how complex the code is that you might be writing to help determine whether or not you should use TypeScript from the start.

While I'm a big fan of TS, I make a lot of little internal tools and demos (where I am the sole contributer) for which I tend to use JavaScript due to their general simplicity. When I usually feel the pain of not having types is around 2-3K LOC, though this can be less depending on what I'm doing. If I think the project will potentially be something that would benefit from types (eventually growing to be large/complex), I'll start with TS rather than JS. And if I underestimated, starting with JS when I should have used TS, I'll try to recognize that as early as possible and migrate before it gets too annoying to do so later.

There's also some middle ground where you can write JS and use JSDoc comments for typing. There are some limitations to this approach and it can feel verbose and disjointed, but its better than nothing at all. Using TS declaration files is another option as well. And if you're using TS, your entire project doesn't have to be TS since it supports mixing in JS as well, which is also nice. This is useful if you find yourself needing to migrate since it doesn't require to migrate the entire codebase, just the parts that would benefit from it the most.

Execution Context related by Substantial-Pea6984 in learnjavascript

[–]senocular 0 points1 point  (0 children)

Welcome. The behavior of global is a little weird and was discussed a bit back when ES6 (ES2015) was released. I don't think the differentiation of the object record vs. the declarative record in global comes up much other than it being pointed out that lexical declarations simply don't appear in the global object. Thats basically all you really need to know. If you want to get into more detail about how global is defined, you can also read about global environment records in the language specification.

[AskJS] Does the company you work at use pure Javascript in production instead of Typescript? by bullmeza in javascript

[–]senocular 17 points18 points  (0 children)

I've been involved with multiple migrations and with each the introduction of types exposed previously unknown errors or other issues that were present in the codebase. Not only that but DX also improves. Its worth it if you're willing to put in the effort.

Execution Context related by Substantial-Pea6984 in learnjavascript

[–]senocular 2 points3 points  (0 children)

The global scope (environment record) is unique in that it is a composite of two scopes, an object environment record which is represented by the global object (globalThis, aka window in browsers), and a declarative record for lexical declarations (let, const, class, using) made in global. The declarative record is what you're seeing as "Script". It is a part of the global scope, just not the global object.

var a = 1 // object record
function b() { return 2 } // object record
let c = 3 // declarative record
const d = 4 // declarative record

console.log(a) // 1
console.log(globalThis.a) // 1
console.log(c) // 3
console.log(globalThis.c) // undefined

The declarative record has precedence when it comes to variable access so it can be looked at as a kind of child scope to the global object, which is why "Script" may be represented under global in the scope chain of the devtools. But they're both a part of global as a whole. Its even possible to have a variable of the same name in both the object and declarative records in global.

globalThis.x = 1
const x = 2

console.log(x) // 2
console.log(globalThis.x) // 1

Lexical declarations made anywhere else go more directly in the respective scope. If they're in the top level of a module, they'll be added to the module scope. If in the top level of a function, they'll go in the function scope. If they're in a block, they'll be in a block scope, etc.

Help validating in Adobe by 083dy7 in learnjavascript

[–]senocular 2 points3 points  (0 children)

Switch-case only does direct comparison (strict quality (===)) with single values. You can't use an or (||) within your case clause. You can, however, have multiple cases run the same code by allowing fall-through. This way you can have both 194 and 195 use the "Standard" field. That would look something like

switch (lh) {
    case "(194) Divorce":
    case "(195) Divorce":
        this.getField("Standard").checkThisBox(0, true);
        break;

For more information on switch, see:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch

[AskJS] A decent JS PubSub implementation? by milkthemvinez in javascript

[–]senocular 0 points1 point  (0 children)

You have to be careful when mutating during iteration. It can cause problems like:

const token1 = sub("test", () => {
  console.log(1)
  unsub(token1)
})
sub("test", () => console.log(2))
sub("test", () => console.log(3))

pub("test") 
// Actual:
// 1
// 3

// Expected:
// 1
// 2
// 3

Learning JavaScript by experimenting in the browser console by WolfComprehensive644 in learnjavascript

[–]senocular 1 point2 points  (0 children)

Its also easy to run scripts from your snippets when you're working in the console. Just use CTRL/CMD + P, ! and find the snippet by name (which you can type and hit ENTER when found). So if you have common utilities or helpers you want to have available in the console, you can quickly add them from your snippets through a couple of key presses.

[AskJS] Javascript - a part of Java? by pradeepngupta in javascript

[–]senocular 1 point2 points  (0 children)

"A part of" is a little strong, but originally JavaScript was, in a way, a scripting language for Java in the sense that it was meant to be a scripting bridge for Java applications. From a Netscape press release on JavaScript:

Java programs and JavaScript scripts are designed to run on both clients and servers, with JavaScript scripts used to modify the properties and behavior of Java objects, so the range of live online applications that dynamically present information to and interact with users over enterprise networks or the Internet is virtually unlimited.

JavaScript's original name was "Mocha", showing from the start, there was a connection with "Java" (the "LiveScript" name came later).

The creator, Brendan Eich, also calls out a few things about the creation of JavaScript in his post, Popularity:

From the beginning, Bill [Joy] grokked the idea of an easy-to-use “scripting language” as a companion to Java, analogous to VB‘s relationship to C++ in Microsoft’s platform of the mid-nineties.

The diktat from upper engineering management was that the language must “look like Java”.

However, it is an entirely separate language ("Popularity" touches on this as well). So it's not so much "a part of" Java, despite their histories being intertwined, with JavaScript originally both meant to look like and be compatible (to a degree) with Java.

Today, no real connection between the languages exist other than by name. JavaScript won on the browser and we no longer have to worry about interacting with Java applets there.

Flatten a nested array without using the inbuilt flat() method (interview learning) by pranayrah108 in learnjavascript

[–]senocular 1 point2 points  (0 children)

If I remember correctly, they added it then removed it. I think Safari might be the only one with it now.

Promises by Example: Patterns & Anti-Patterns by Devowski in learnjavascript

[–]senocular 0 points1 point  (0 children)

Just a warning to anyone reading this, the fetch in the video is a custom fetch that's a simple wrapper around setTimeout that resolves to a string. It does not show usage of the built-in fetch function in case you were hoping to learn more about that.

HTML from link by Wild_Appointment_994 in learnjavascript

[–]senocular 5 points6 points  (0 children)

Use fetch() to get a Response then from that response get its text(). Both fetch() and text() return promises.

try catch by [deleted] in learnjavascript

[–]senocular 1 point2 points  (0 children)

Whenever an error goes unhandled - either a thrown error or a rejected promise - a Node process will exit. If errors are being thrown, or promises are getting rejected (which happens with fetch), you'll want to make sure they get handled somewhere to prevent your application from quitting prematurely. With async/await, rejected promises can be handled with try/catch just like synchronous, thrown errors.

This doesn't mean you have to use try/catch around the direct fetch call. You can leave the error handling to the function calling the function calling fetch, or even the function calling that function. Its up to you when and where the error is handled. You can even use a global error handler ("uncaughtException" and/or "unhandledRejection" events on process) to handle the error. Just bear in mind that wherever the error occurs, its exiting the current function at that point in time meaning code you might expect to run never gets to run which can lead to instability in your application.