jow- / ucode

JavaScript-like language with optional templating
ISC License
87 stars 24 forks source link

[FEAT] make arrow functions keep this context (as in js) #122

Closed huafu closed 1 year ago

huafu commented 1 year ago

Will it be possible to make arrow functions (() => { ... }) to keep the this context, as it is in javascript?

function methodA() {
  for (let item in someArray) { // side note, why choosing "in" keyword instead of "of" as in JS?
    this.methodB(item); // this works or course
  }

  const self = this;
  map(someArray, (item) => {
    this.methodB(item); // this fails, but would work in js
    // in js following line is true
    self === this;
  });
}
jow- commented 1 year ago

Hmm, they are supposed to already.

The following simple example works as expected for me:

x = {
        methodA: function() {
                const self = this;
                map([1,2,3], (item) => this.methodB(item, self));
        },

        methodB: function(item, self) {
                warn(`Item: ${item}, Same: ${self === this}\n`);
        }
};

x.methodA();

It yields:

$ ucode /tmp/test.uc
Item: 1, Same: true
Item: 2, Same: true
Item: 3, Same: true

Can you provide a stand-alone testcase reproducing your issue?

huafu commented 1 year ago

Hi @jow- , sorry to answer that later, I'm still trying to narrow-down the issue.

I DO confirm that in most cases the context is kept when using arrow functions. But due to an issue in the project I'm working, I thought this was not the case.

The project in which is the issue can't be shared badly, tho here is the piece that fail:

    // whitin an object
    forSessionId: function (sessionId) {
        return cache.call(sessionId, () => this.create(sessionId));
    }

it fails on this.create(...) call, saying left-hand side is not a function, left-hand side being the create part.

Now same exact code, just using a variable to hold this, and it works, no more left-hand side is not a function:

    // whitin an object
    forSessionId: function (sessionId) {
        const self = this;
        return cache.call(sessionId, () => self.create(sessionId));
    }

I'll try more to find out where/what exactly causes that...

huafu commented 1 year ago

@jow- I also discovered that arrow-functions with brackets (() => {...} in opposite to () => xxx) will return what the last statement would return with a return at the beginning of the line, I guess the last item in the stack.

1. without brackets

const arr = [];
const fn = () => push(arr, 'hello');
print(fn()); // will print the return value of `push`, which is expected (I meant, expected in JS)

2. with brackets

const arr = [];
const fn = () => {
  // arrow function with brackets
  push(arr, 'hello');
}
print(fn()); // will print the return value of `push`, which is NOT expected (again I meant, not expected in JS)

The fn function of 2 in JS would return undefined (hence null in ucode). I don't know if that is expected or not. Lemme know if I should open a new issue for that.

side note: the original issue opened here may then be on my side, tho I still need to investigate more

jow- commented 1 year ago

@huafu - the implicit return issue for arrow functions is addressed in a pending PR - did you manage to find a reproducer for the original issue?

huafu commented 1 year ago

Hi @jow- , sorry that I haven't answered before. I could not figure out where my this was being null, and the implicit return didn't change a thing (or I haven't come back in my repository to the correct commit for testing)... Tho I'll continue to investigate as soon as I get more time for it and/or when that issue comes back in my new code.

jow- commented 1 year ago

I'll close this as the requested behavior alignment with JS has been implemented.