是否可以在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 中的obj.PIPETHIS(f)
类似于kotlin 中的obj.WITH(f)
类似于kotlin 中的obj.WITHTHIS(f)
类似于kotlin 中的
let
相似run
also
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的cloneWith
或cloneDeepWith
,它类似于Kotlin的apply
。
const transformedObject = cloneWith(originalObject, (value) => {
value.propertyOne = "x"
value.propertyTwo = "y"
return value
})