Muhammad Muzammil
Muhammad Muzammil

Reputation: 1439

Kotlin like scope functions (let, also, apply, run) in Javascript?

Is it possible to create Kotlin like scope functions in Javascript/Typescript? Is there any library that does it?

Reference: https://kotlinlang.org/docs/reference/scope-functions.html

Upvotes: 13

Views: 7516

Answers (3)

T.J. Crowder
T.J. Crowder

Reputation: 1075079

No, you can't do that in JavaScript or TypeScript. But depending on why you're trying to do it, destructuring can help.

The closest you can get is to use the deprecated with statement (I don't recommend it), which adds an object to the top of the scope chain, so any freestanding identifier references are checked against the object's properties:

function example(o) {
    with (o) { // deprecated
        console.log(answer);
    }
}
const obj = {
    answer: 42
};
example(obj); // Outputs 42

There are several problems with with, though, which is why it's disallowed in the strict variant of JavaScript (which is the default inside modules, class constructs, and other new scopes created in ES2015+, as well as any function or script with "use strict"; at the beginning). Those same problems are why it's not supported in TypeScript (TypeScript will copy it over to the transpiled JavaScript code, but with an error, and it will use any as the type of symbols inside the with; example).

Another close version is to pass an object to a function that uses destructuring in its parameter list:

function example({answer}) {
    console.log(answer);
}
const obj = {
    answer: 42
};
example(obj); // Outputs 42

but a major caveat there is that you can't assign new values to properties that way (and worse, if you try — for instance, with answer = 67 — it updates the parameter's value but not the object's property value).

To deal with that, you might use destructuring inside the function instead, with const so you don't forget you can't update the value (or to get an early error if you try):

function example(o) {
    const {answer} = o;
    console.log(answer);
    // answer = 67;   // <== Would cause error
    // o.answer = 67; // <== Would work
}
const obj = {
    answer: 42
};
example(obj); // Outputs 42

Upvotes: 8

Extremely
Extremely

Reputation: 540

If anyone is still looking for an answer, there is an excellent library for those scope functions for javascript (I am not affiliated):

https://github.com/TheDavidDelta/scope-extensions-js

Upvotes: 7

Gabriel
Gabriel

Reputation: 21

While not exactly what you're looking for, a pattern that I use let a lot for in Kotlin is

val thing = nullable?.let{ // case if not null } ?: run { // case if null }

The closest I've come to this in Javascript (well, typescript) in terms of readability and ergonomics is something like:

const thing = some?.deeply?.nested?.nullable?.thing ?? (() => {
// case if null
})

Which gets you halfway there. :)

Upvotes: 2

Related Questions