0

A common use-case for Object.assign is to modify (or flat out replace) the properties of an object without changing the reference to the object, so other things that have that reference are also updated.

Is there a way to do this with the contents of a function as well?

So, for example:

const a = () => console.log('a');
const b = a;
doSomethingMagicalHere(b, () => console.log('b'));
b(); // prints 'b'
a(); // prints 'b'
samanime
  • 25,408
  • 15
  • 90
  • 139
  • 2
    why not just replace the function on the object holding that function? make it a let instead of a const – the8472 Mar 02 '17 at 18:23
  • The equivalent would be that the reference to the function would be the same between both. Think similar to pointers in C. You can change the value of it without changing the reference, so when you change the contents of one, the contents of the other are updated as well. It's kind of a stretch, and probably doesn't exist, but I'm hoping there is something I'm unaware of. A correct answer would make my example code function as described. – samanime Mar 02 '17 at 18:27
  • @the8472 My example is overly simplistic, but in the real example, I'm trying to mock/stub a React component which is actually a function, and the only way to do so would be to update what the function does without just assigning a new value to it (in a test file), as the new value wouldn't be reflected in the actual code. – samanime Mar 02 '17 at 18:29
  • 2
    @samanime You probably should have included that information in your question. See http://meta.stackexchange.com/a/66378/140350 – Jordan Running Mar 02 '17 at 18:30
  • *"without just assigning a new value to it"* - again, you're not giving a reason. – the8472 Mar 02 '17 at 18:35
  • possible duplicate of [How do i redefine what my function does without damaging its properties?](http://stackoverflow.com/q/21939726/1048572) or [Is it possible to modify a function itself?](http://stackoverflow.com/q/17609931/1048572) – Bergi Mar 02 '17 at 19:08
  • I understand the XY problem . I also have a question out there for my specific problem. This is a potential solution, but I wanted to explore the question in isolation as well as an intellectual exercise. – samanime Mar 02 '17 at 19:35

2 Answers2

0

Is there a way to modify/replace the contents of a function?

No, that's outright impossible. The behaviour of a function (i.e. what calling it will do) is immutable in Javascript.

Of course, if you know beforehand that you will want to alter the behaviour of the function, you can make the function a closure that relies on some external, exchangeable state to determine what it should do:

const a = function f(...args) { return f.contents.call(this, ...args); }
a.contents = () => console.log('a');
a(); // prints 'a'
Object.assign(a, {contents(){ console.log('b') }});
a(); // prints 'b'
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks, I had thought of something like this as well. Unfortunately in my particular case, it's React that's creating the function converting from ES6 and JSX Harmony syntax, so I can't directly control how the function happens. – samanime Mar 02 '17 at 19:37
  • @Bergi your response "The behaviour of a function (i.e. what calling it will do) is immutable in Javascript." reminded me of this question: http://stackoverflow.com/questions/41478219/proxying-a-recursive-function – Hrishi Mar 02 '17 at 19:41
  • @samanime This doesn't have to do anything with syntax (you do the same in ES5), you just need to control the function definition (or be able to overwrite it). Maybe you should [ask a new question](http://stackoverflow.com/questions/ask) with your actual use case – Bergi Mar 02 '17 at 19:51
  • @Bergi I know. What I meant is I don't have the opportunity to wrap it up, because I'm actually writing classes (using the class syntax) that are getting converted to these functions. I have asked a question with my specific problem, but I wanted to ask this question as well to see if there was anything clever that I wasn't aware of. – samanime Mar 02 '17 at 20:47
  • I see, thanks. No, there's nothing clever you missed. – Bergi Mar 02 '17 at 21:02
  • Accepted this question as it's probably the closest to doing what I was looking for that's actually possible. – samanime Mar 08 '17 at 14:59
-1

First, there is one thing I don't understand in your sample, the use of const. Why use const b if you reassign b on line 3 ?

Anyhow, in Javascript, most variables use references. So, for instance, in the following code, the const a is defined as a function and the variable b is a reference to a, so when assigning a new function to b, you actually assign a as well.

const a = () => console.log('a');
var b = a;
b = () => console.log('b');
a(); // prints 'b'

I hope I didn't miss your point.

Edit #1

Rather than declaring a function a as a const which will be reassigned afterward, I'd store that function in a static object. The object reference/pointer itself is then a constant but its content, its properties, aren't considered as immuatables. (https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.whv1jizih)

// Define a constant reference/pointer to the static object oA
const oA = {
 // Define mutable property "f"
 f: () => console.log('a')
};
// Define an other const ref to the same object called oB
const oB = oA;
// Update the value pointed by the oB.f ref
oB.f = () => console.log('b');
// Call oB.f // 'b' expected
oB.f();
// Call oA.f // 'b' expected
oA.f();
// Using Object.defineProperty
Object.defineProperty(oA, 'f', {
 __proto__: null
  , value: () => console.log('f')
});
// Call oB.f // 'f' expected
oB.f();
// Call oA.f // 'f' expected
oA.f();
Booster2ooo
  • 1,373
  • 9
  • 11
  • My example was a bit off. I've updated it. The point of const though is I don't want to change the **reference**, just it's value (kind of like pointers in C). – samanime Mar 02 '17 at 19:36
  • Even if I still don't understand the *whys*, I updated my comment. Have a look at Edit#1 – Booster2ooo Mar 04 '17 at 10:00
  • Assigning to b will not affect a in the first case. Javascript does use references, as is evident from passing (references to) arrays and objects around and mutating them, but in this case you assign a new reference to b that points to the new function. A C analog of sorts would be that a and b are both pointers and you assign a new pointer to b and expect a to update as well. – Ilja Everilä Mar 04 '17 at 10:28