有没有可能在Javascript/Typescript中创建类似Kotlin的作用域函数?有没有什么库可以做到这一点?参考:https://kotlinlang.org/docs/reference/scope-functions.html
qyzbxkaa1#
不,你不能在JavaScript或TypeScript中这样做,但是根据你为什么要这样做,解构可以帮助你。最接近的方法是使用已弃用的with语句,该语句将一个对象添加到作用域链的顶部,因此任何独立的标识符引用都将根据对象的属性进行检查:
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";开头的函数或脚本中的默认值)。另一个近似的版本是将对象传递给在其参数列表中使用解构的函数:
class
"use strict";
function example({answer}) { console.log(answer); } const obj = { answer: 42 }; example(obj); // Outputs 42
但是一个主要的警告是你不能用这种方式给属性赋值(更糟糕的是,如果你尝试的话--例如,对于answer = 67--它会更新参数的值,而不是对象的属性值)。
answer = 67
为了解决这个问题,你可以在函数内部使用const来进行反结构化,这样你就不会忘记你不能更新这个值(或者如果你尝试了,就会得到一个早期的错误):
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
ttcibm8c2#
如果有人还在寻找答案,有一个很好的库,里面有JavaScript的作用域函数(我没有加入):https://github.com/TheDavidDelta/scope-extensions-js
63lcw9qa3#
https://www.npmjs.com/package/lazymacro这个包提供了您需要的特性,并且它的实现非常简单(通过Object.defineProperty,请参见code)。
Object.defineProperty
obj.PIPE(f)
let
obj.PIPETHIS(f)
run
obj.WITH(f)
also
obj.WITHTHIS(f)
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
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));
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 })
这让你走了一半。:)
4条答案
按热度按时间qyzbxkaa1#
不,你不能在JavaScript或TypeScript中这样做,但是根据你为什么要这样做,解构可以帮助你。
最接近的方法是使用已弃用的
with
语句,该语句将一个对象添加到作用域链的顶部,因此任何独立的标识符引用都将根据对象的属性进行检查:但是
with
有几个问题,这就是为什么它在JavaScript的严格变体中是不允许的(这是模块、class
构造和ES 2015+中创建的其他新作用域,以及任何以"use strict";
开头的函数或脚本中的默认值)。另一个近似的版本是将对象传递给在其参数列表中使用解构的函数:
但是一个主要的警告是你不能用这种方式给属性赋值(更糟糕的是,如果你尝试的话--例如,对于
answer = 67
--它会更新参数的值,而不是对象的属性值)。为了解决这个问题,你可以在函数内部使用
const
来进行反结构化,这样你就不会忘记你不能更新这个值(或者如果你尝试了,就会得到一个早期的错误):ttcibm8c2#
如果有人还在寻找答案,有一个很好的库,里面有JavaScript的作用域函数(我没有加入):
https://github.com/TheDavidDelta/scope-extensions-js
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
然后你可以这样写:
此外
它为
Promise
提供了作用域函数,可以将您从await
/then
的地狱中拯救出来promise.THEN(f)
promise.WAIT(f)
示例:
8ulbf1ek4#
虽然这并不是您要寻找的模式,但我在Kotlin中经常使用
let
的模式是在可读性和人体工程学方面,我在Javascript(嗯, typescript )中最接近这一点的是:
这让你走了一半。:)