Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
echinopsis
Apr 13, 2004

by Fluffdaddy

reversefungi posted:

The addEventListener function registers a callback function, whose execution is delayed until everything is exhausted in the main thread and you've entered the event loop. However the "registering" happens on that main thread, and in this case you were invoking a function and registering its output, hence the immediate call.

If you're not super familiar with the event loop and really want to dig in, this video is worth watching and will pay itself back quickly by saving you hours of debugging annoying js stuff:

https://youtu.be/8aGhZQkoFbQ

I watched this video and I think now your post makes more sense to me lol.

Adbot
ADBOT LOVES YOU

bigperm
Jul 10, 2001
some obscure reference
I'm messing around with Svelte and have a little demo working. npm run dev works perfectly but when I do a build it puts the files into a /dist folder. I try to open my index.html in that folder locally and I get a cors error for my js file and my css file fails to load, despite everything being on my computer.

I feel like I'm missing some big picture thing here.

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


Are you serving it, or just opening the local file? The latter causes the CORS issue, i believe.

bigperm
Jul 10, 2001
some obscure reference
Just opening it. Yeah, it works if I use the 'Go Live' vs-code extension to serve it.

echinopsis
Apr 13, 2004

by Fluffdaddy

fakemirage posted:

Haven't gone through everything, but I noticed the following line.

This will execute the clickOnCrimeButton function and place the result as the event handler. You'll probably want something like this:

JavaScript code:
    // add function to the button for when it is clicked
   document.getElementById(structOfCrimesIterator.name).addEventListener("click", () => clickOnCrimeButton(buttonIndex));
Which means that you'll call clickOnCrimeButton when the event happens and not before then.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

EDIT: Yeah, I think that's the problem. It's basically the same as writing the following.
JavaScript code:
var clickOnCrimeButtonOutput = clickOnCrimeButton(buttonIndex); // undefined
document.getElementById(structOfCrimesIterator.name).addEventListener("click", clickOnCrimeButtonOutput); // .addEventListener("click", undefined)

I've been looking and trying to understand arrow functions, and I can't work out why changing it to an arrow function works?

when you post:
JavaScript code:
var clickOnCrimeButtonOutput = clickOnCrimeButton(buttonIndex); // undefined
document.getElementById(structOfCrimesIterator.name).addEventListener("click", clickOnCrimeButtonOutput); // .addEventListener("click", undefined)
you're trying to say that what I had originally posted is the equivalent to that... but why?

why does
code:
   document.getElementById(structOfCrimesIterator.name).addEventListener("click",clickOnCrimeButton(buttonIndex));
split into two commands? if I am understanding correctly? does anyone understand why I am confused?

chaosbreather
Dec 9, 2001

Wry and wise,
but also very sexual.

echinopsis posted:

I watched this video and I think now your post makes more sense to me lol.

I think the root issue here isn't the event system, it's actually syntax. In Javascript, if you write a function call anywhere, like myFun(blob) or myFun(), you are calling that function then and there on the spot. There's not even a way to make where that wouldn't happen in a function definition. This isn't true in a bunch of programming languages but it is at least consistent. You can pass functions by reference, though, without calling them, by leaving off the parens, like myFun.

The basic intuition here is mathematical – just like maths, the innermost parentheses are calculated first.
So for
JavaScript code:
x(cat, blog(s, d + s(a))
1. s(a) is called
2. d is added to the result of step 1.
3. blog is called with s and the result of step 2.
4. x is called

As you can see, everything is immediate here, and will continue to be immediate, unless one of our parameters creates as new scope, like fakemirage suggests, so for
JavaScript code:
x2(cat, () => blog(s, d + s(a))
1. an anonymous function is created
2. x2 is called with cat and a reference to that function

At this point, the function x2 has the function has a parameter, like any other type of parameter. x2 can save that function to a different scope which can be called later, or call it immediately, or call it out of band entirely. Everything inside the function, in this case, s(a) and then blog(...) will only get called once that function gets called.

Hope that makes some sense. The best advice I can give you is to really build a confidence in when things happen in Javascript. The most fundamental part of understanding any system, be it computational, mechanical, biological, or astronomical, is timing. So console.log everything until nothing surprises you any more and get real comfy with the debugger.

bigperm
Jul 10, 2001
some obscure reference

echinopsis posted:

I've been looking and trying to understand arrow functions, and I can't work out why changing it to an arrow function works?

when you post:
JavaScript code:
var clickOnCrimeButtonOutput = clickOnCrimeButton(buttonIndex); // undefined
document.getElementById(structOfCrimesIterator.name).addEventListener("click", clickOnCrimeButtonOutput); // .addEventListener("click", undefined)
you're trying to say that what I had originally posted is the equivalent to that... but why?

why does
code:
   document.getElementById(structOfCrimesIterator.name).addEventListener("click",clickOnCrimeButton(buttonIndex));
split into two commands? if I am understanding correctly? does anyone understand why I am confused?
addEventListener takes a type (in this case 'click') and an event handler. The event handler can either be an object with a handleEvent() method or a function. If you give it clickOnCrimeButton(buttonIndex) you are actually sending return value of that function as the event handler, not the function itself. An arrow function lets you send an anonymous function that wraps the function you want to call, which can then be executed on the event.

minato
Jun 7, 2004

cutty cain't hang, say 7-up.
Taco Defender
When you have a function like:
code:
print(sqrt(49), sqrt(16))
the actual order of events is:
code:
1. [evaluate first parameter]  call sqrt(49) --> answer = 7
2. [evaluate 2nd parameter]  call sqrt(16) --> answer = 4
3. call print(7, 4)
In other words, the inner functions get executed first and their responses stored, and those are passed to the outer function.

addEventListener wants 2 parameters: a string with an event type ("click"), and a reference to a function to execute when that click happens. So when if you call:
code:
...addEventListener("click", myClickHandler)
... the JS parser has exactly that; the string "click", and a reference to the function myClickHandler. (Note! myClickHandler is not being executed here! Using the function name by itself just means "a reference to this function".)

Now consider this:
code:
...addEventListener("click", myClickHandler(foo))
This is wrong! Why? Because the JS parser is doing this internally:
code:
1. [evaluate first parameter] --> "click"
2. [evaluate second parameter] --> call myClickHandler with parameter "foo", and store the result. 
     This result is likely to be null, since myClickHandler likely doesn't return anything. --> null.
3. call addEventListener("click", null)
So in other words, it breaks because you're telling the browser to call Null when it gets the click event.

So why does wrapping this in an arrow function work?
code:
...addEventListener("click", () => myClickHandler(foo))
It will become clear if you expand out that shorthand:

code:
...addEventListener("click", () => myClickHandler(foo))

  --- is equivalent to ---

...addEventListener("click", function() {
    myClickHandler(foo)
})

  --- is equivalent to ---

let blahblah = function() {
    myClickHandler(foo)
}
...addEventListener("click", blahblah)
In other words, the arrow function is defining a new function (I called it "blahblah" but it's actually anonymous), and all that function does is call myClickHandler(foo). So when addEventListener is called, it's being passed "click" and the reference to the anonymous function, not to myClickHandler directly. When the click finally occurs, JS will call the anonymous function, which in turn will finally call myClickHandler(foo), which is what you actually want.

chaosbreather
Dec 9, 2001

Wry and wise,
but also very sexual.

Practical example. You're making a robot that stops Canadians from stealing your phone.

JavaScript code:
robot.addBehaviour(phoneSteal, warnOrElse("put down the phone or i will shoot", shootToKill(canadian)))
Putting in to practice what we know about parenthesises though, that the innermost stuff in score gets executed first, this isn't what we're looking for but it is very funny.

The robot will kill the Canadian, as soon as it starts up, then warn "put down the phone or i will shoot", then start looking for potential phone thieves, which it will do absolutely nothing when it detects them, because warnOrElse doesn't return anything.

This is because what we've said is, hey, robot.addBehaviour, call phoneSteal with the result or warnOrElse with the result of shootToKill. That is not what we want to be saying, we want to be saying, hey, robot.addBehaviour, I'm giving you a bit of code you should run later when you feel you have to.

JavaScript code:
robot.addBehaviour(phoneSteal, () => warnOrElse("put down the phone or i will shoot", shootToKill(canadian)))
This also gives us the opportunity to get a parameter of our own when that gets called later.

JavaScript code:
robot.addBehaviour(phoneSteal, (certainty) => {
  if (certainty > 80) {
    warnOrElse("put down the phone or i will shoot", shootToKill(canadian))
  }
})
Very good but also still wrong. Now it won't kill our Canadian buddy immediately, but still as soon as it's reasonably sure that it will steal the phone. After which it will warn his maple-syrup-stained corpse. Because we're saying to warnOrElse, here's the result of shoot to kill, not here's a procedure I want you to use later, when the warning fails.

JavaScript code:
robot.addBehaviour(phoneSteal, (certainty) => {
  if (certainty > 80) {
    warnOrElse("put down the phone or i will shoot", () => shootToKill(canadian))
  }
})
And again, this gives us the opportunity to pass parameters from that callback.

JavaScript code:
robot.addBehaviour(phoneSteal, (certainty) => {
  if (certainty > 80) {
    warnOrElse("put down the phone or i will shoot", (ehCount) => {
      for (let i = 0; i < max(ehCount, 1); i++) {
         shootToKill(canadian)
      }
    )
  }
})
In this way our robot can be ironic, which is crucial for great user experience.

echinopsis
Apr 13, 2004

by Fluffdaddy
wow guys poo poo you’ve given me a good series of answers. I won’t have a chance to sit down and get my head around it until tomorrow, but gosh I really appreciate your help and support here.

I feel like I am making a lot of break throughs, where my time is leaning more toward making progress on my program rather than spending time trying to work out how the heck I do anything

AlphaKeny1
Feb 17, 2006

I'm doing a deep dive into JS to prepare for getting grilled in interviews. I read most of the "Javascript the good parts". I'm on class instantiation/OOP and prototyping right now and I think I somewhat get it. My background on OOP is from using Java in school, so JS is pretty different.

Anyway I'm reading this medium article and I'm a little lost on the subclassing section.
https://medium.com/@ariel.salem1989/pseudoclassical-subclass-instantiation-in-javascript-6e54a13ea3c4

quote:

Subclassing:
You may be thinking to yourself, that’s cool, but what if I wanted to use our redCar instantiation properties on some other car? Here’s where Subclassing comes into play. Much like Class Instantiation, we can create a Subclass based on the Class operator that inherits characteristics from the Class operator AND has its own unique properties:

var Location = function(color, movementSpeed, location) {
this.location = location;
Car.call(this, color, movementSpeed); // calling the previous
// Class operator allows our new subclass to inherit its
// properties.
}

Location.prototype = Object.create(Car.prototype); // this sets up
// the prototype relationship between the Subclass instantiation
// and the original Class (Car).
Location.protoytpe.constructor = Location.prototype; // since the
//previous line overwrote our prototype constructor, we must
//setup our Subclass relationship to its Constructor prototype
//object.
Now if we wanted to create a redCar and yellowCar with the same properties, we can do so without having to rewrite the location method one both of them:

var redCar = new Location("red", 10, 12);
//redCar = {color:"red", movementSpeed: 10, location: 12};
var yellowCar = new Location("yellow", 8, 15);
//yellowCar = {color:"yellow", movementSpeed: 8, location: 15};
var blueCar = new Car("blue", 6);
//blueCar = {color:"blue", movementSpeed: 6};
Since the blueCar is an instance of the Car Class, it does not have access to the Location subclass properties. This one-way relationship allows the Location Subclass to inherit properties from the Car Class while preventing the Car Class from accessing those properties.

So you can .call() on a class to pass it's this to a function/class, allowing your new function to inherit whatever you called? I'm lost on the next two lines, assigning Object.create(Car.prototype) and overwriting the constructor on the Location prototype. I don't think I get that part.

Also, are there any tips for what I should know and prepare for? My last job hunt I was never really asked a lot of front end/JS questions in an interview setting.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
You're driving into topics that prove you know how some of JavaScript's trickier syntax and concepts work. But, I'm a little bit surprised by the topic. I don't think classes are widely used in JavaScript, I mean you can use them. I will from time to time for data structures but, nothing complex. And usually I prefer to create a function that just returns an object and leave it at that.

React has gone fully functional, for example, and most everything else has too I think. Keep it simple and all of that.

camoseven
Dec 30, 2005

RODOLPHONE RINGIN'
In nearly 7 years of professional JavaScripting I have never written a class

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
JavaScript makes using 'this' a total nightmare. What is 'this' well that depends on how the function was called and whether it's a lambda and on and on. That's why I think everyone said forget it.

lunar detritus
May 6, 2009


If during a job interview someone asks about OOP or mentions they use classes in JS, avoid that job.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Most often seen when JavaScript developers used to be Java developers.

AlphaKeny1
Feb 17, 2006

I have a reference who mentioned the phrase pseudoclassical instantiation for a FAANG+ and I had no idea what it was so I was looking into it this morning.

And yeah I loving hate this in JS.

Why would you .call() for an object to inherit this... can't I just stick to binding methods?

Also my team moved to light OOP in JS so guess why I'm interviewing.

Doom Mathematic
Sep 2, 2008

AlphaKeny1 posted:

I'm doing a deep dive into JS to prepare for getting grilled in interviews. I read most of the "Javascript the good parts". I'm on class instantiation/OOP and prototyping right now and I think I somewhat get it. [...]

OK I think you are understandably confused for several reasons:

(1) JavaScript has prototype-based inheritance, not class-based inheritance,
(2) JavaScript does have a modern class syntax which works pretty much how you would expect coming from a Java background but this is syntactic sugar for the old prototype-based system,
(3) the book java script: The Good Parts is from 2008, fully predating ES6, which was the birth of modern, usable JavaScript and introduced the class syntax,
(4) the article you're reading, despite being written in 2017, after class was added, also appears to totally ignore this and work in an entirely pre-ES6 world, and
(5) the article is absolutely bananas. For example, it seems to be trying to create a class Location as a subclass of Car??? It suggests this line of code:

JavaScript code:
var redCar = new Location("red", 10, 12);
????

Here's how classes actually work in modern JavaScript.

JavaScript code:
class Car {
  constructor (color, movementSpeed) {
    this.color = color
    this.movementSpeed = movementSpeed
  }
}

const redCar = new Car('red', 10)
console.log(redCar.color) // "red"
console.log(redCar.movementSpeed) // 10
There is nothing else you need to know.

Doom Mathematic
Sep 2, 2008
Oh, and inheritance is achieved using:

JavaScript code:
class BlueCar extends Car {
  constructor (movementSpeed) {
    super('blue', movementSpeed)
  }
}
For more information, here is some actual documentation about JavaScript classes, including inheritance.

Remember again that this is technically all syntactic sugar for the old prototype-based inheritance model, which does still exist. The Medium article you linked gets some of the details of that old model correct but in other cases it is flat-out wrong even ignoring the typographical errors. This article does a better job of explaining that older approach for achieving the same thing. Yes, it is still absolutely ghastly and I highly advise not bothering to learn the specifics.

AlphaKeny1
Feb 17, 2006

Thank you for the writeup, that is literally how I used classes in my last project complete with the extends keyword. Like I haven't used prototype poo poo that I have been reading in any of these places. I will def read that link you posted.

echinopsis
Apr 13, 2004

by Fluffdaddy






alright thanks guys. I really do understand now why my original code was failing. the notion of arrow functions is less intuitive to me, but I am working on that.

thanks again. good old something awful huh :unsmith:

AlphaKeny1
Feb 17, 2006

echinopsis posted:

the notion of arrow functions is less intuitive to me, but I am working on that.


Think of it as just another way of declaring a function.

const example = (parameter) => {
}

is the same as

const example = function(parameter) {
}

it's easier to write the arrow function.

So the w3school has this example in their event listener page:
element.addEventListener("click", function(){ alert("Hello World!"); });

which of course can be re-written to:
element.addEventListener("click", () => {alert("Hello World!");});

which is way easier.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

AlphaKeny1 posted:

is the same as
Though they're not quite the same if there's a "this" used inside the function.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense

AlphaKeny1 posted:

const example = (parameter) => {
}

I much prefer

function example (parameter) {
}

syntax. But I'm the only one unfortunately.

MrMoo
Sep 14, 2000

A lot of time people are cargo culting the former without need of this capture. It’s usage should really be minimal as it only makes it harder to read.

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


I really like the
code:
const add = (a) => (b) => a + b;
const add5 = add(5);
pattern myself.

I think that curried functions look clunky when written using the function keyword.

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
I find that almost in all cases I'm doing something inside of the first function so it look like.
code:
const add = (a) => {
    const whatever = 'hello';
    // etc...
    return (b) => {
    };
};
Which I prefer to write as.
code:
function add (a) {
    const whatever = 'hello';
    // etc...
    return function (b) {
    };
}
A lot of the time this difference coincides with whether or not the developer likes semicolons at the end of statements. Usually the people that omit them prefer the inline thing for some reason, whereas defining functions without using const doesn't need them either way.

Maybe it has to do with it looking clean vs it being easy to read, which is a minor distinction.

AlphaKeny1
Feb 17, 2006

I think for me it's an issue of consistency. Like if I'm doing

code:
.then(result => {

});

// or

addEventListener("click", e => handleClick(e));

// or

[...nodeElements].forEach(node => {
	// manipulate node
})
it makes sense for me to declare other functions that way

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


AlphaKeny1 posted:

code:


addEventListener("click", e => handleClick(e));

I know this is just a simple example, so I'm not calling you out and this is just for the people less familiar with it, but the callback doesn't need to be wrapped in a lambda in this case. You can just do

code:


addEventListener("click", handleClick);

instead. It does the exact same thing, minus that extra unused closure.

I've seen this so many times in production code that i had to say something.

smackfu
Jun 7, 2004

Does it actually make any difference?

Armauk
Jun 23, 2021


AlphaKeny1 posted:

I'm doing a deep dive into JS to prepare for getting grilled in interviews.

Do yourself a favor and focus on frameworks: Node and React.

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


smackfu posted:

Does it actually make any difference?

No, not really. I haven't dug into it, but I would expect the optimizer to deal with it in this case. I just found that a lot of juniors I've been working with are not aware that you don't need to wrap a callback in a pass thru lambda like that. But in the end, whatever.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

gbut posted:

No, not really. I haven't dug into it, but I would expect the optimizer to deal with it in this case. I just found that a lot of juniors I've been working with are not aware that you don't need to wrap a callback in a pass thru lambda like that. But in the end, whatever.
I'd be pleasantly surprised if the optimizer makes them equivalent.

It's always frustrating, though, that you *do* have to do
addEventListener("click", () => someClass.someFunction())
rather than
addEventListener("click", someClass.someFunction)

(One of the few things that's better in Dart than JS/Typescript.)

And because of that awkwardness I would tentatively recommend just always doing the pass through lambda because it prevents both that mistake and the original mistake that started up this whole topic (accidentally calling the function rather than passing a reference to the function).

Nolgthorn
Jan 30, 2001

The pendulum of the mind alternates between sense and nonsense
Sometimes your function accepts additional parameters and not using an extra lambda can cause problems.
code:
const myFunction = (item, isHidden = false) => {
    // code here
};

const myArray = myItems.map(myFunction);
The IsHidden parameter receives the index from the map function. So everything past index 0 will be considered "truthy" by your code and who the heck knows what happens. This is why people like Typescript, or in a lot of cases just being explicit with extra lambdas.
code:
const myArray = myItems.map(item => myFunction(item));
Explicit lambdas also reduce the chances that code will break later, it makes it easier to understand what's going on, stuff like that. I don't mind them, unless the function being passed in is at least defined in the same file.

echinopsis
Apr 13, 2004

by Fluffdaddy
at some stage while working on this I must have made a change and I don't know what, but I am unable to work out why a css selector isn't working on a div

when I inspect it in chrome, it's clear it's got the class on the div, but it's like the css isn't even there in my stylesheet. it's not like it's being overridden, just doesn't seem to be working at all.

I have this at the end of my css file
code:
.log {
  display: flex;
  border: 2xp;
  border-color: white;
  border-style: solid;
  flex: 0 0;
  height: 40%;

  color: white;
  text-transform: none;
  padding: 5px;
}
and there is a picture showing that class selected in the inspector but.. idk what I've done to stop it applying any of that css


you can view the source at http://crimecommitter.com

fakemirage
Nov 6, 2012

Can't see the haters.

echinopsis posted:

idk what I've done to stop it applying any of that css

The html doesn't look right.
HTML code:
<div ="class" ="log" id="logID">
should be
HTML code:
<div class="log" id="logID">
i.e. property=value

fakemirage fucked around with this message at 14:34 on Jun 13, 2022

barkbell
Apr 14, 2006

woof

echinopsis posted:

at some stage while working on this I must have made a change and I don't know what, but I am unable to work out why a css selector isn't working on a div

when I inspect it in chrome, it's clear it's got the class on the div, but it's like the css isn't even there in my stylesheet. it's not like it's being overridden, just doesn't seem to be working at all.

I have this at the end of my css file
code:
.log {
  display: flex;
  border: 2xp;
  border-color: white;
  border-style: solid;
  flex: 0 0;
  height: 40%;

  color: white;
  text-transform: none;
  padding: 5px;
}
and there is a picture showing that class selected in the inspector but.. idk what I've done to stop it applying any of that css


you can view the source at http://crimecommitter.com

code:
="class"="log"
should be
code:
class="log"

echinopsis
Apr 13, 2004

by Fluffdaddy
oh my god what a fuckin numbnuts

thanks guys

LongSack
Jan 17, 2003

echinopsis posted:

oh my god what a fuckin numbnuts

thanks guys

Also, it’s probably just a typo in your post, but you have your border width set to “2xp” rather than “2px”

Adbot
ADBOT LOVES YOU

echinopsis
Apr 13, 2004

by Fluffdaddy
yeah 2 experience . that’s um not a typo


lol

next step is figuring out date()

i’ve just tested positive for covid so guess i have a week at home to work it out lol

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply