Kotlin喜欢Javascript中的作用域函数(let、also、apply、run)吗?

km0tfn4u  于 2023-02-18  发布在  Java
关注(0)|答案(4)|浏览(110)

有没有可能在Javascript/Typescript中创建类似Kotlin的作用域函数?有没有什么库可以做到这一点?
参考:https://kotlinlang.org/docs/reference/scope-functions.html

qyzbxkaa

qyzbxkaa1#

不,你不能在JavaScript或TypeScript中这样做,但是根据你为什么要这样做,解构可以帮助你。
最接近的方法是使用已弃用的with语句,该语句将一个对象添加到作用域链的顶部,因此任何独立的标识符引用都将根据对象的属性进行检查:

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

但是with有几个问题,这就是为什么它在JavaScript的严格变体中是不允许的(这是模块、class构造和ES 2015+中创建的其他新作用域,以及任何以"use strict";开头的函数或脚本中的默认值)。
另一个近似的版本是将对象传递给在其参数列表中使用解构的函数:

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

但是一个主要的警告是你不能用这种方式给属性赋值(更糟糕的是,如果你尝试的话--例如,对于answer = 67--它会更新参数的值,而不是对象的属性值)。

为了解决这个问题,你可以在函数内部使用const来进行反结构化,这样你就不会忘记你不能更新这个值(或者如果你尝试了,就会得到一个早期的错误):

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
ttcibm8c

ttcibm8c2#

如果有人还在寻找答案,有一个很好的库,里面有JavaScript的作用域函数(我没有加入):
https://github.com/TheDavidDelta/scope-extensions-js

63lcw9qa

63lcw9qa3#

https://www.npmjs.com/package/lazymacro
这个包提供了您需要的特性,并且它的实现非常简单(通过Object.defineProperty,请参见code)。

  • obj.PIPE(f)类似于Kotlin中的let
  • obj.PIPETHIS(f)类似于Kotlin中的run
  • obj.WITH(f)类似于Kotlin中的also
  • obj.WITHTHIS(f)类似于Kotlin中的apply

然后你可以这样写:

["I", "am"]
    .WITH(v => v.push("lazynode."))
    .WITH(console.log)
    .PIPE(v => v.join(" "))
    .PIPE(v => console.log(`${v}`))
    ?.PIPE(v => console.log("null safety features can be used together!"));

此外

它为Promise提供了作用域函数,可以将您从await/then的地狱中拯救出来

  • promise.THEN(f)
  • promise.WAIT(f)

示例:

Promise.resolve({})
    .WAIT(async local => local.datax = await getSomeRemoteData())
    .WAIT(async local => local.datay = await getSomeRemoteData())
    .WAIT(async local => local.dataz = await getSomeRemoteData())
    .WAIT(async local => await doSomething(local.datax, local.datay, local.dataz));
8ulbf1ek

8ulbf1ek4#

虽然这并不是您要寻找的模式,但我在Kotlin中经常使用let的模式是

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

在可读性和人体工程学方面,我在Javascript(嗯, typescript )中最接近这一点的是:

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

这让你走了一半。:)

相关问题