Kotlin像作用域函数(让,也,应用,运行)在Javascript?



是否可以在Javascript/Typescript中创建Kotlin类型的作用域函数?有这样的图书馆吗?

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

不行,你不能在JavaScript或TypeScript中这样做。但是,根据为什么要尝试这样做,解构可以有所帮助。

您可以得到的最接近的是使用已弃用的with语句,它将对象添加到作用域链的顶部,因此根据对象的属性检查任何独立标识符引用:

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

with有几个问题,虽然,这就是为什么它在JavaScript的严格变体中不被允许(这是默认的内部模块,class结构,以及在ES2015+中创建的其他新作用域,以及任何函数或脚本与"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

如果有人还在寻找答案,有一个很好的库用于javascript的范围函数(我不隶属):

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

https://www.npmjs.com/package/lazymacro

这个包提供了你需要的功能,它的实现非常简单(通过Object.defineProperty,见代码)。

  • 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!"));

AND ADDITION

它为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));

虽然不是你想要的,但我在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
})

这让你到达了一半。:)

查看NPM包scoped-values:

https://www.npmjs.com/package/scoped-values

支持如下操作

const doubleValue = $$(data.val).let(it => it * 2).value // 20
const undefinedValue = $$(data.undefined_value).let(it => it * 2) // undefined
$$(data.obj)
.let((it) => {...it, b: 2})
.run(it => console.log(it));
// console output: { a: 1, b: 2 }
$$(data.arr)
.let((it) => [0, ...it])
.map(it => it * 2)
.filter(it => it < 5)
.also(it => console.log(it));
// console output: [0, 2, 4]

您可以使用Lodash的cloneWithcloneDeepWith,它类似于Kotlin的apply

const transformedObject = cloneWith(originalObject, (value) => {
value.propertyOne = "x"
value.propertyTwo = "y"
return value
})

最新更新