-1

EDIT 2: Why has this very specific question been marked as a duplicate of this very conceptual one: What's the difference between passing by reference vs. passing by value?. If someone else had the same question as me, they wouldn't end up with this one on Google by searching for it and - even if they did - it wouldn't answer their question.

EDIT: Thanks everyone for your help so far. Pretty difficult stuff to understand from my point of view. The reason I'm doing this is that I've set up a function which I'm calling multiple times and in which I define a variable (a unique one with each call). I need to be able to refer back to each unique variable afterwards. Here is my actual attempted code below. What would the right way to do this be?

let newSeq1
let newSeq2
function sequenceClip(sample, length, sequenceVariable) {
        let currentPosition = Tone.Transport.position
        let whenToStart
        if (currentPosition === '0:0:0') {
            whenToStart = '0:0:0'
        } else {
            const barToStartOn = +currentPosition.slice(0, currentPosition.indexOf(':'))
            whenToStart = `${barToStartOn + 1}:0:0`
        }
        sequenceVariable = new Tone.Sequence((time, note) => {
            sampler.triggerAttackRelease(note, '4m', time)
        }, [sample], length).start(whenToStart);
    }

    loop1.addEventListener('mousedown', () => {
        sequenceClip("C3", '1m', newSeq1)
    })
    loop2.addEventListener('mousedown', () => {
        sequenceClip("C#3", '4m', newSeq2)
    })

How do I pass a variable into a function in Javascript to be assigned a value. E.g.:

Why does the variable not get assigned the value 5? And what's the way around this?

let a
function defineVariable(var2beDefined) {
   var2beDefined = 5
}
defineVariable(a)

console.log(a === 5)
Ant
  • 221
  • 1
  • 3
  • 8
  • 1
    A scalar value is not mutable. You can have it be a property of an object or an entry of an array if you want a mutable solution, or you can just return the value and assign it to the variable. – Alexander Nied Feb 03 '22 at 15:54
  • 1
    Is there a specific reason you want to do this? Typically you would assign the value returned from the function e.g. `let a = someInitializerFunction()` – jarmod Feb 03 '22 at 16:00
  • @jarmod I've edited the question to provide a bit more context. Presumably there is a right approach here that I'm just missing. The only other thing I can think of is to drop the 'let' and just define the variables globally in the function, but that's pretty gross! What am I missing?! – Ant Feb 03 '22 at 16:15
  • @lusc Thanks, that does some of the conceptual explanation. Still not clear on what my best approach would be though - mine is more of a specific and practical question. My question was marked as a duplicate of that one which doesn't seem right to me. – Ant Feb 03 '22 at 16:17
  • `newSeq1 = sequenceClip("C3", '1m')` and have the `sequenceClip` function end with `return new Tone.Sequence(...)`. And if both `newSeq1` and `newSeq2` are considered global variables then it's OK to declare them in global scope with `let` as you are currently doing. – jarmod Feb 03 '22 at 16:18
  • @jarmod Thanks again. The issue is, I'd like to refer back to the variable without calling the sequenceClip function again. So I don't think that would work for me. Unless I'm missing the point? – Ant Feb 03 '22 at 16:21
  • Why do you think you would have to call the sequenceClip function again? The value of `newSeq1` at any given time is the value that was last assigned to it in the mousedown handler via `newSeq1 = sequenceClip("C3", '1m')`. Note that code is *not* `let newSeq1 = sequenceClip("C3", '1m')` which would declare a new, minimally scoped variable. – jarmod Feb 03 '22 at 16:24
  • @jarmod Brilliant! Yes of course! Thank you for your help. I wish I could mark your comment as the accepted answer. – Ant Feb 03 '22 at 16:30
  • Regarding why your question was closed: I think it's partially valid and that you partially fell victim to [an XY problem](https://meta.stackexchange.com/q/66377/354747). The scope of your original question prior to edits you were attempting to pass a scalar variable by reference. This was ultimately just a misguided approach and a better solution using vars in the parent scope was provided. If you had just asked your edit at the outset this would probably not have been closed, but the core question is still asking how to assign to a scalar var by reference. – Alexander Nied Feb 07 '22 at 14:51
  • Also, FWIW, asking why your question was closed _probably_ belongs in the comments, not in the body of the main question. I could be wrong about that, though. – Alexander Nied Feb 07 '22 at 14:52

2 Answers2

2

Reassigning an identifier, by itself, never has any side-effects (in most circumstances) - the only change resulting from someIdentifier = someNewValue will be when other parts of the code reference that same someIdentifier.

If you want to pass in something to be assigned to, pass in a function which, when called, assigns to the outer variable.

let a;
function defineVariable(callback) {
  callback(5);
}
defineVariable(newVal => a = newVal);

console.log(a === 5)

The only time that assigning to an identifier will have side effects is if:

  • Inside a function with a simple argument list, you reassign one of the parameters (in which case the arguments object will be changed as well)
  • You're using ES6 modules, and you reassign an identifier that's being exported, in which case other modules that import it will see the change as well
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
2

You would typically write an initializer function that returns a value and assign that return value to the relevant global variable. For example:

let newSeq1
let newSeq2

function sequenceClip(sample, length, sequenceVariable) {
    let currentPosition = Tone.Transport.position
    let whenToStart

    if (currentPosition === '0:0:0') {
        whenToStart = '0:0:0'
    } else {
        const barToStartOn = +currentPosition.slice(0, currentPosition.indexOf(':'))
        whenToStart = `${barToStartOn + 1}:0:0`
    }

    return new Tone.Sequence((time, note) => {
        sampler.triggerAttackRelease(note, '4m', time)
    }, [sample], length).start(whenToStart);
}

loop1.addEventListener('mousedown', () => {
    newSeq1 = sequenceClip("C3", '1m')
})

loop2.addEventListener('mousedown', () => {
    newSeq2 = sequenceClip("C#3", '4m')
})

Note that both newSeq1 and newSeq2 will be undefined until the first mousedown/mouseup events.

jarmod
  • 71,565
  • 16
  • 115
  • 122