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
Kwolok
Jan 4, 2022
Another dumb question. I am inheriting an old bad system.

A part of the project exposes some secrets and tokens on the clientside. They are just straight up in the code. Obviously thats bad but even putting them in .env files to be loaded at runtime still means somewhere eventually those values are bundled into the bundle.

So in my mind there are two better practices here:
1) The location the secrets and tokens access should instead be accessed on the backend and not directly on the frontend, and then it should go through normal auth to get the resource (instead of directly to the resource, independent of user as it currently exists). This way we can use our normal auth methods to ensure access to the external endpoint, and we don't have to worry abotu exposing secrets/tokens. OR:
2) Split the bundle into an auth-ed bundle and an un-authed bundle. In this case the unauthed bundle is really just login, and the auth bundle is the app and contains the bundled secrets/tokens. Still not ideal for a few reasons but at least non-authed users will never be able to gain access to these secrets/tokens without having at least a valid login.

Option 1 seems better to me, but I am curious if there are other considerations I should take into account.

Adbot
ADBOT LOVES YOU

smackfu
Jun 7, 2004

(1) is typically best practice, yes.

Kwolok
Jan 4, 2022
One more dumb question.

I am using libraries that require sharearraybuffers, which requires me to enable some pretty restrictive cors settings. However our login is through google identity services. Is it possible to have cors set up for just hte login page to be unrestrictive, set the access tokens to local storage (yeah I know this is bad), and then flip back to the main app that now has the access tokens in local storage with the restrictive cors. I hate cors.

necrotic
Aug 2, 2005
I owe my brother big time for this!
How you respond to CORS is entirely on you, so yes it’s possible. This allows you to only permit things such as what you need on specific pages (or all pages except specific exceptions).

Sad Panda
Sep 22, 2004

I'm a Sad Panda.
This intro to JS course I'm doing has just introduced the unary plus operator and suggested going through the code we've worked on to change it from Number() to the + to convert because 'it is cleaner'. That lead to a definite bit of denial from me and the Python mindset of 'Explicit is better than implicit.' Surely Number() is more readable and more explicit? What's the advantage of using what to me could easily be mistaken for a seemingly random plus sign that was meant to concatenate or perform addition?

AlphaKeny1
Feb 17, 2006

wtf I didn't even know that was in js, I come from java and so I'm used to parseInt or Number. I guess I can see the case that you're typing less.

necrotic
Aug 2, 2005
I owe my brother big time for this!
I definitely prefer Number, though if you have a string I want turned into a number I’m going to use parseInt

fuf
Sep 12, 2004

haha

fuf posted:

I'm using React contexts rather than zustand

As my little adventures with React continue, I'm now trying to refactor some stuff to use zustand instead of context providers.

One thing I can't figure out is how to replace the parameters that I was passing to the context providers.

Like right now I have stuff like:
JavaScript code:
<TagContextProvider tags={tags}>
	<AddTag>
	<TagList>
</TagContextProvider>


// Somewhere else
<TagContextProvider tags={newTags}>
	<AddTag>
	<TagList>
</TagContextProvider>
So I can reuse the same components but pass them different bits of state data.

If I wanna replace <TagContextProvider> with a zustand "store", then what's a good way to reuse Components but with different state stores or different elements of the same store?

fuf
Sep 12, 2004

haha
Just to update on the above, the issue is covered in this thread:

https://github.com/pmndrs/zustand/issues/128

Weirdly, the solution is just to use React context providers to pass in a particular store to a component.

So it feels like I've come full circle. If I'm still using context providers then why would I use zustand rather than just storing the state directly in the context like I was before?

The motivation for moving to zustand was to try and avoid the issue where components using a context provider have to re-render every time anything in the context changes. I'm assuming that if the context contains a zustand store then all the components are going to re-render when the store changes? I haven't actually tested this so maybe not.

Ima Computer
Oct 28, 2007

Stop all the downloading!

Help computer.

fuf posted:

So it feels like I've come full circle. If I'm still using context providers then why would I use zustand rather than just storing the state directly in the context like I was before?

The motivation for moving to zustand was to try and avoid the issue where components using a context provider have to re-render every time anything in the context changes. I'm assuming that if the context contains a zustand store then all the components are going to re-render when the store changes?

As long as you're memoizing the newly instantiated zustand store at the Provider level, the reference to the store never changes, so the context won't cause a re-render (unless you redefine/recreate your store)

If you have global state which doesn't need multiple instances, then you don't need to use a Context at all, since all consumers can share a direct import reference to the same instance of the store.

Ima Computer fucked around with this message at 14:53 on Mar 8, 2023

fuf
Sep 12, 2004

haha
Hmm ok thank you. It might be time to finally learn what memoize means.

Ima Computer posted:

If you have global state which doesn't need multiple instances, then you don't need to use a Context at all, since all consumers can share a direct import reference to the same instance of the store.

yeah I have a handle on this, and zustand is really good for that stuff.

But I thought I was being clever by making big chunks of the UI reusable, like the same interface but with different (state) data loaded in. And this is where it gets tricky because it doesn't know which store to use.


fuf fucked around with this message at 14:59 on Mar 8, 2023

LifeLynx
Feb 27, 2001

Dang so this is like looking over his shoulder in real-time
Grimey Drawer
code:
import Head from 'next/head'
import { useState, useEffect } from 'react'

export default function Home() {
  const handleSubmit = (e) => {
    e.preventDefault()
    setCardName(e.target[0].value)
    cardSearch()
  }

  const [cardName, setCardName] = useState('')
  const [results, setResults] = useState('')

  const cardSearch = () => {
    fetch(`https://api.scryfall.com/cards/search?&q=${cardName}`).then((res) =>
      res.json().then((data) => setResults(data))
    )
  }

  useEffect(() => {
    //Does something go here?
  }, [])

  return (
    <>
      <Head>
        <title>Trading Post</title>
        <meta name="description" content="Description goes here." />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <form onSubmit={handleSubmit}>
          <input type="text" className="card-input"></input>
          <button className="card-input__submit">Search</button>
        </form>

        {JSON.stringify(results)}
      </main>
    </>
  )
}
Clicking the Search button once searches for the default state set in cardName, which is nothing. Clicking the button again does work though. I seem to recall a way to "warm up" the app using useEffect, but I can't for the life of me figure out what to put there. I also remember reading recently that useEffect was getting phased out as a way to do pretty much everything. What's the answer to get the search to work on the first click?

Soviet Space Dog
May 7, 2009
Unicum Space Dog
May 6, 2009

NOBODY WILL REALIZE MY POSTS ARE SHIT NOW THAT MY NAME IS PURPLE :smug:

LifeLynx posted:

Clicking the Search button once searches for the default state set in cardName, which is nothing. Clicking the button again does work though. I seem to recall a way to "warm up" the app using useEffect, but I can't for the life of me figure out what to put there. I also remember reading recently that useEffect was getting phased out as a way to do pretty much everything. What's the answer to get the search to work on the first click?

It's because React state variables are a bit tricky and updating them doesn't work how most people would assume. If you want to see what is happening put console.log(e.target[0].value,cardName) just before and after the setState(e.target[0].value) line. Basically the setState doesn't update the state in your functions when it is called, it updates them *after* your functions are completed. They are still using the value of cardName from before the setState was called. There's three ways of fixing your problem:

1) (Probably the standard) Turn your form into a controlled component form. I think you are trying to do this (that's why you have cardName as a state variable), but haven't. Make the value of the input cardName and use an onChange to update cardName when the input field is changed, rather than on submitting the form.

2) Change cardsearch to take the card name as an input and use cardSearch(e.target[0].value). You can possibly get rid of the cardName state variable since it isn't actually needed.

3) Have a useEffect that is depending on cardName that calls cardsearch, probably condtionally on the value of cardSearch to stop it fetching on mount. This is by far the worst.

The easiest way to understand useEffect is that it it a bit of code that runs whenever one of its dependencies change in value. A lot of people use it when they don't need to since if your code is the only thing changing the value of a state variable, you can just put the code in a function and call that instead of relying on useEffect (which is slow, can run when you don't expect it and possibly cause infinite loops of variable changes). For whatever reason it also runs once when the component mounts, so it can be used to fetch data on mount. This meant that a lot of people learned useEffect as the magical inital data fetch hook rather than what it is.

LifeLynx
Feb 27, 2001

Dang so this is like looking over his shoulder in real-time
Grimey Drawer

Soviet Space Dog posted:

It's because React state variables are a bit tricky and updating them doesn't work how most people would assume. If you want to see what is happening put console.log(e.target[0].value,cardName) just before and after the setState(e.target[0].value) line. Basically the setState doesn't update the state in your functions when it is called, it updates them *after* your functions are completed. They are still using the value of cardName from before the setState was called. There's three ways of fixing your problem:

1) (Probably the standard) Turn your form into a controlled component form. I think you are trying to do this (that's why you have cardName as a state variable), but haven't. Make the value of the input cardName and use an onChange to update cardName when the input field is changed, rather than on submitting the form.

2) Change cardsearch to take the card name as an input and use cardSearch(e.target[0].value). You can possibly get rid of the cardName state variable since it isn't actually needed.

3) Have a useEffect that is depending on cardName that calls cardsearch, probably condtionally on the value of cardSearch to stop it fetching on mount. This is by far the worst.

The easiest way to understand useEffect is that it it a bit of code that runs whenever one of its dependencies change in value. A lot of people use it when they don't need to since if your code is the only thing changing the value of a state variable, you can just put the code in a function and call that instead of relying on useEffect (which is slow, can run when you don't expect it and possibly cause infinite loops of variable changes). For whatever reason it also runs once when the component mounts, so it can be used to fetch data on mount. This meant that a lot of people learned useEffect as the magical inital data fetch hook rather than what it is.

Thanks, #2 is what I went with. There's eventually going to be more than one input and I don't want to make an API call every time that one input field updates, so I have the whole thing on form submit.

#3 is what I learned the last time I was serious about learning React. I probably relied on it too heavily, but I see that was a common mistake!

fuf
Sep 12, 2004

haha
Here's a React state value/reference issue that I don't understand.

I have a zustand store that uses immer and looks kind of like:
JavaScript code:
export default create(
	immer((set) => ({
		tags: [],
		currentTag: null,

		setCurrentTag: (id) => {
	        	set((state) => {
		        	state.currentTag = state.tags.find((tag) => tag.id === id);
		        });
	      },
	}))
)
I assumed that after beting set, currentTag would be a reference to one of the tags in the array, i.e. they would be the same object. But instead currentTag is its own object, and updates to it don't affect the version in the array and vice versa.

How can I make currentTag a reference to an object in the array?

Sad Panda
Sep 22, 2004

I'm a Sad Panda.
When you're coding, how do you decide which version to aim for? This course I'm working through is often explaining the original way to do it, and then how it can now be done. It used to be done by ... but in ES6/ES2020/ES2022 this new functionality was added to make it easier to do. One example being how to get the last element of an array.

JavaScript code:
arr[arr.length-1]; // traditional
arr.at(-1); // added in ES2022

MrMoo
Sep 14, 2000

In WebPack land it’s almost always been: develop for the latest and transpile to ES5, and possibly ES6 if generous.

I’ve been perusing the VSCode base, and there is a lot of ES5-only code due to Electron being clunky.

MrMoo fucked around with this message at 17:51 on Mar 11, 2023

Sad Panda
Sep 22, 2004

I'm a Sad Panda.

MrMoo posted:

In WebPack land it’s almost always been: develop for the latest and transpile to ES5, and possibly ES6 if generous.

I’ve been perusing the VSCode base, and there is a lot of ES5-only code due to Electron being clunky.

Interesting. So does this mean that the main advantage of new features is mainly that they provide a simpler way of accomplishing a similar task rather than adding actual new functionality? This makes it faster for developers but doesn't change things in the backend?



Other question...

The course I'm doing has some HTML like this...

HTML code:
      <nav class="nav">
        <img
          src="img/logo.png"
          class="nav__logo"
        />
        <ul class="nav__links">
          <li class="nav__item">
            <a class="nav__link" href="#section--1">Features</a>
          </li>
...
and uses this code to model the idea of event bubbling

JavaScript code:
const randomColor = () =>
  `rgb(${randomInt(0, 255)},${randomInt(0, 255)},${randomInt(0, 255)})`;

document
  .querySelector(".nav__link")
  .addEventListener("click", function (e) {
    this.style.backgroundColor = randomColor();
    console.log(`link ${e.target}`);
  });
document
  .querySelector(".nav__links")
  .addEventListener("click", function (e) {
    this.style.backgroundColor = randomColor();
    console.log(`container ${e.target}`);
  });
document
.querySelector(".nav")
.addEventListener("click", function (e) {
  this.style.backgroundColor = randomColor();
  console.log(`nav ${e.target}`);
});
It says that when an event takes place on a node, the event comes down the DOM from root to the target. Then it bubbles up. On its way back up this leads to the listeners on the parent nodes being triggered and changing to a random colour.

But if I change the click event to a mouseenter event, that doesn't trigger the parent nodes to change colour.

To me, that makes it seem less like the event is bubbling up, and more like it triggered them all because in clicking on the eg the a tag, I also clicked on its parents too. Whereas mouseentering the a tag didn't see me mouseenter the parents.

Am I wrong? Do only certain events propogate/bubble?

necrotic
Aug 2, 2005
I owe my brother big time for this!
Yes, only some events bubble.

https://developer.mozilla.org/en-US/docs/Web/API/Event/bubbles

MDN is a fantastic resource for (web focused) JavaScript

Roadie
Jun 30, 2013

fuf posted:

Here's a React state value/reference issue that I don't understand.

I have a zustand store that uses immer and looks kind of like:
JavaScript code:
export default create(
	immer((set) => ({
		tags: [],
		currentTag: null,

		setCurrentTag: (id) => {
	        	set((state) => {
		        	state.currentTag = state.tags.find((tag) => tag.id === id);
		        });
	      },
	}))
)
I assumed that after beting set, currentTag would be a reference to one of the tags in the array, i.e. they would be the same object. But instead currentTag is its own object, and updates to it don't affect the version in the array and vice versa.

How can I make currentTag a reference to an object in the array?

Why do you care about them being the same object in the first place?

smackfu
Jun 7, 2004

Sad Panda posted:

Interesting. So does this mean that the main advantage of new features is mainly that they provide a simpler way of accomplishing a similar task rather than adding actual new functionality? This makes it faster for developers but doesn't change things in the backend?

Anything that’s actually new (rather than just syntactic sugar), will require a polyfill for the older browsers.

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!
I was curious whether doing a bunch of drawImage to a single canvas, or having a bunch of canvas objects moving around, would be better for a game-style "redrawing the entire screen every frame" sort of thing, so I made a little test. Turns out drawing 2000 64x64 sprites from off-screen canvases with drawImage runs at 6fps on my machine, versus moving 2000 on-screen canvases with the same content runs at 20fps. (So obviously it would be even more-better to use moving elements if there's some part of the content that doesn't update.)

Though now I feel like I should also test how it handles with a 3D context, making the sprites as textures associated with triangle-pairs, and refreshing a vertexbuffer to move them around. But for my purposes I'm pretty sure on-screen canvases is going to be adequate, and so much less annoying to code than the real high performance option.

Edit: to be clear, "for my purposes" is a lot fewer than 2000 on-screen items. And probably also interacting with some vector-drawing.

roomforthetuna fucked around with this message at 22:49 on Mar 11, 2023

fuf
Sep 12, 2004

haha

Roadie posted:

Why do you care about them being the same object in the first place?

I have a component for updating a tag that uses currentTag from the zustand store, and also an "updateTag" option that takes a tag ID:

JavaScript code:
 const tag = useTagStore((state) => state.currentTag);
 const updateTag = useTagStore((state) => state.updateTag);
The issue is that updateTag updates the version of the tag in the array of tags (as it should), but because currentTag is a separate object, the component doesn't reflect the changes that have just been made so you still see the old values.

e: the workaround I came up with is to just store an ID in currentTag instead of an actual tag object, so now my update component looks like:

JavaScript code:
  // ID version
  const tagId = useTagStore((state) => state.currentTagId);
  useEffect(() => {
  if (tagId) {
     tag = tags.find((tag) => tag.id === tagId);
     }
  }, [tagId]);
but it feels way messier.

fuf fucked around with this message at 12:36 on Mar 13, 2023

Ape Fist
Feb 23, 2007

Nowadays, you can do anything that you want; anal, oral, fisting, but you need to be wearing gloves, condoms, protection.
Seeing NestJS claim the 3rd spot on the NPM javascript frameworks list does nothing but validate my entire theory that Angular's architecture was always the correct way of doing all of this poo poo and that React's popularity isn't due to it being good, but rather popular. This is a controvesial but ultimately correct opinion.

barkbell
Apr 14, 2006

woof
no

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice

:emptyquote:

death cob for cutie
Dec 30, 2006

dwarves won't delve no more
too much splatting down on Zot:4
Student found something weird that I can't seem to explain to my own satisfaction via looking at the MDN/EMCAScript specification, so I'm not sure if I'm reading the wrong thing or what.

Here's some bullshit JavaScript.

code:
var sampleObject = {'key1': 28, 'key2': 384, 'key4': 12}
sampleObject['key4', 'key1'] // returns 28
sampleObject['keyX', 'key1', 'key4'] // returns 12
sampleObject['key4', 'key1', 'keyX'] // returns undefined
Why can I put multiple strings inside the brackets here? Obviously the behavior is that it returns the value associated with the last key (assuming it exists), but why does the interpreter even accept multiple arguments for whatever function is actually called (this is where I think I'm not finding the right thing) when I use square brackets here?

teen phone cutie
Jun 18, 2012

last year i rewrote something awful from scratch because i hate myself

death cob for cutie posted:

Student found something weird that I can't seem to explain to my own satisfaction via looking at the MDN/EMCAScript specification, so I'm not sure if I'm reading the wrong thing or what.

Here's some bullshit JavaScript.

code:
var sampleObject = {'key1': 28, 'key2': 384, 'key4': 12}
sampleObject['key4', 'key1'] // returns 28
sampleObject['keyX', 'key1', 'key4'] // returns 12
sampleObject['key4', 'key1', 'keyX'] // returns undefined
Why can I put multiple strings inside the brackets here? Obviously the behavior is that it returns the value associated with the last key (assuming it exists), but why does the interpreter even accept multiple arguments for whatever function is actually called (this is where I think I'm not finding the right thing) when I use square brackets here?


Ima Computer
Oct 28, 2007

Stop all the downloading!

Help computer.

death cob for cutie posted:

Why can I put multiple strings inside the brackets here? Obviously the behavior is that it returns the value associated with the last key (assuming it exists), but why does the interpreter even accept multiple arguments for whatever function is actually called (this is where I think I'm not finding the right thing) when I use square brackets here?

You can put any JS expression you want inside a property accessor that uses square brackets syntax.

The "evaluates to last value" behavior is just how the comma operator works.

Its rules apply any time you shove a comma somewhere you wouldn't normally expect to see one.

death cob for cutie
Dec 30, 2006

dwarves won't delve no more
too much splatting down on Zot:4

Ima Computer posted:

You can put any JS expression you want inside a property accessor that uses square brackets syntax.

The "evaluates to last value" behavior is just how the comma operator works.

Its rules apply any time you shove a comma somewhere you wouldn't normally expect to see one.

oh-ho! much is explained now, thank you

Data Graham
Dec 28, 2009

📈📊🍪😋



That makes total sense once you know about it, but now I'm just trying to imagine troubleshooting it without that knowledge

Or doing that on purpose

death cob for cutie
Dec 30, 2006

dwarves won't delve no more
too much splatting down on Zot:4
Yeah; my current job is basically writing an introductory programming/JavaScript textbook for my company's part-time students. They don't get as much instructor time as others, and are coming in as complete and total newbies, so a. a lot of things confuse them, b. they don't necessarily have an immediate expert on hand and c. they're not great at reading documentation/Googling code stuff yet. I'm writing a lot of examples of how stuff breaks or otherwise behaves weird based on what students have shown me previously.

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!

Data Graham posted:

That makes total sense once you know about it, but now I'm just trying to imagine troubleshooting it without that knowledge

Or doing that on purpose
Enjoying the idea of doing that in ways where you can't just remove the nonsense as well, like the extra clauses are necessary.
code:
someObject[x+="\n", (q=5), "someKey"] = "hello";
Edit: I especially like that I'm not sure whether that makes x+="someKey" or the thing it looks like, not sure about the precedence of comma versus += operator.

roomforthetuna fucked around with this message at 01:40 on Mar 16, 2023

is that good
Apr 14, 2012
I think some minifiers use the operator a lot, but yeah I haven't really seen it used for anything other than turning your code into a golf course.

e: MDN to the rescue as always

MDN - Comma operator (,) posted:

This is commonly used to provide multiple updaters to a for loop's afterthought.
[...]
Another example [...] is processing before returning. This is especially useful for one-line arrow functions.

is that good fucked around with this message at 05:39 on Mar 20, 2023

Doom Mathematic
Sep 2, 2008
For loops have named parts, and one of them is the "afterthought"? I had no clue.

death cob for cutie
Dec 30, 2006

dwarves won't delve no more
too much splatting down on Zot:4

Doom Mathematic posted:

For loops have named parts, and one of them is the "afterthought"? I had no clue.

I also only recently learned this when I had to start writing some more technical stuff for students.

necrotic
Aug 2, 2005
I owe my brother big time for this!

Doom Mathematic posted:

For loops have named parts, and one of them is the "afterthought"? I had no clue.

Every piece of syntax is going to have a specific name :)

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Doom Mathematic posted:

For loops have named parts, and one of them is the "afterthought"? I had no clue.
I haven't seen this either, so I asked chatgpt about it.

In a for loop, there are three conditions - these are referred to as initialization, condition, and afterthought. Do we know who or which standard started calling the third condition "the afterthought"?

chatgpt 4 posted:

It is difficult to pinpoint a specific individual or standard that started referring to the third part of a for loop as "the afterthought." The term "afterthought" is a colloquialism that has been used by some programmers to describe the third part of a for loop, which is often referred to as the "update" or "increment" statement. This term likely arose informally within the programming community as a way to describe the role of the third part in a for loop, which typically involves updating the loop control variable.

The use of the term "afterthought" might not be widespread or universally recognized. In formal documentation and programming literature, the three parts of a for loop are usually referred to as the "initialization," "condition," and "update" or "increment" statements.

That's true, it's not universally recognized. I see it on the mdn website's definition of a for loop - are there any programming language standards that refer to the "update" statement as "afterthought"?

chatgpt 4 posted:

After searching through various programming language documentation and standards, it appears that none of them officially refer to the "update" statement as "afterthought." MDN (Mozilla Developer Network) is a valuable resource for web developers, but it is not an official language standard.

The term "afterthought" might be used informally in some resources or among programmers, but it is not part of any official language specification or standard. The official terms for the three parts of a for loop in most programming languages are "initialization," "condition," and "update" or "increment."

For example, the ECMAScript (JavaScript) standard, C++ standard, and Python's PEP documents, which outline the specifications and standards for their respective languages, do not use the term "afterthought." They all consistently use "update," "increment," or similar terms to describe the third part of a for loop.

I'm seeing "afterthought" crop up on websites teaching new programmers how to use for loops, and I do see some recent stackoverflow stuff referring to afterthought, but it's not as if this name comes from any official standard.

fakemirage
Nov 6, 2012

Can't see the haters.

Bruegels Fuckbooks posted:

That's true, it's not universally recognized. I see it on the mdn website's definition of a for loop - are there any programming language standards that refer to the "update" statement as "afterthought"?
Looks like MDN switched to "afterthought" last year to align with eslint. eslint got it from wikipedia back in 2015. Wikipedia doesn't have it any longer, but it was initially added back in 2012, referencing a c++ tutorial page in one of the later changes as its source. The c++ page currently doesn't use "afterthought", and I can't find it used on the wayback machine, but it only goes back to 2021.

There was a "citation needed" entry on the usage of "afterthought" added back in 2013 ("Who calls it an afterthought?"), but it was removed in a seemingly unrelated update.

At this point I'm hoping someone updates the wiki page and adds MDN as the source so we can go full circle.

EDIT:
odd, I was sure the wayback machine only had snapshots to 2021 when I checked yesterday, but it actually looks like it has two snapshots from around the time "afterthought" was introduced to the wiki page (20th December 2012).
4th of November 2012
26th of December 2012
In both snapshots the article was written back in June 25th, 2007, and has no mention of "afterthought" on the page.

fakemirage fucked around with this message at 13:30 on Mar 22, 2023

Adbot
ADBOT LOVES YOU

gbut
Mar 28, 2008

😤I put the UN🇺🇳 in 🎊FUN🎉


I never even heard of it before this discussion, and it doesn’t even make that much sense. It’s a bit funny, yes, but if I was interviewing someone and they used that, I’d dock a point.

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