JavaScript analog of java.lang.Optional?
JavaScript analog of java.lang.Optional?
我正在寻找一个客户端JavaScript库,它可以让我编写类似于我可以在其他语言中使用一些选项类型的代码,例如java.lang.Optional.
我的目标是在客户端代码中避免null
/undefined
检查,并使API更明确。
var dictionary = {
key1: 'value1',
key2: 'value2'
}
function getValue(key){
var value = dictionary[key];
if(value !== null && value !== undefined)
return Optional.of(value);
else
return Optional.empty();
}
下面是客户端代码:
var value = getValue('key3');
if(value.isPresent())
console.log('got a value: ' + value.get().toUpperCase());
else
console.log('no value found!');
有时:
var value = getValue('unknown key').orElse('default value');
如果我在Optional.empty()
值上调用get()
,它应该抛出某种Error
。如果我在null
或undefined
上调用Optional.of()
,它也应该抛出
考虑到java.lang.Optional源代码,自己编写一个可选实现应该不会那么困难。
虽然你必须考虑到一些差异,即javascript区分undefined
和null
,但你没有泛型这样的概念,并且Java的map实现被一些人认为是坏的。尽管如此,它还是很容易实现的。
然而,我已经做了一个实现(optional.js)自己,这适合我的需要,你可以使用它,如果你喜欢,但它可能不满足你所有的要求(即of()
不抛出一个异常对未定义或null,但get()
)
function getValue(key){
return Optional.of(dictionary[key]);
}
var value = getValue('key3');
value.ifPresent(function() {
console.log('got a value: ' + value.get().toUpperCase());
});
顺便说一句。像这样的代码
if(value.isPresent())
console.log('got a value: ' + value.get().toUpperCase());
else
console.log('no value found!');
不是Optional的有效用例,因为您可以很容易地将其替换为null/undefined检查。但是如果您需要filter
, map
, flatMap
和ifPresent
这样的方法,您将从中受益更多。
对于那些在2021年仍然对这个感兴趣的人。
tl;博士:
-
始终使用ES可选链。它以JavaScript的方式更具语义性和艺术性(可能与Babel一起)。如:
obj.val?.prop || defaultValue obj.val?.[expr] obj.arr?.[index] obj.func?.(args)
-
使用
Optional
类,它可能是NOT被TypeScript中的其他包支持,如果你只是想深入访问一个对象属性是NOT有点容易。
查看更多信息:
我试着用TypeScript做一个粗略的Optional
类:
import isNil from "../is/isNil";
// isNil = val => val === null || val === undefined
class Optional<T> {
value = null;
constructor(value: T) {
this.value = value;
}
static EMPTY = new Optional(null);
static empty(): Optional<unknown> {
return Optional.EMPTY;
}
static of<U>(value: U): Optional<U> {
return new Optional(value);
}
isPresent(): boolean {
return !isNil(this.value);
}
filter<T>(predicate: (value: T) => Boolean): Optional<T> {
if (!this.isPresent()) {
return this;
}
return predicate(this.value) ? this : Optional.EMPTY;
}
map<T, U>(mapper: (value: T) => U): Optional<U> {
if (!this.isPresent()) {
return this;
}
return Optional.of(mapper(this.value));
}
flatMap<T, U>(mapper: (value: T) => Optional<U>): Optional<U> {
if (!this.isPresent()) {
return this;
}
const mapped = mapper(this.value);
if (isNil(mapped)) {
throw new Error("flatMap will map the value not to null or undefined.");
}
return mapped;
}
orElse<T>(other: T): T {
return isNil(this.value) ? other : this.value;
}
}
在这里你可以看到当我想使用Optional访问property时,它会像下面这样写:
Optional.of(dictionary)
.map((obj)=> {
const descriptors = Object.getOwnPropertyDescriptors(obj)
// ⚠️ when you use like this, it may also cause an error.
return descriptors.key1.value
})
.orElse('defaultValue')
和使用Optional chain
将像这样:
dictionary?.key1 || 'defaultValue'
对于某些使用场景,包含0到1个元素的数组是非常合适的。
它很简单,用于创建和查询的语法很简洁,并且还提供了内置的filter()和map(),这是我使用Optional的主要原因之一:
const one = ["foo"];
const none = [];
console.log("one.isPresent: " + !!one.length);
console.log("none.isPresent: " + !!none.length);
console.log("one.get: " + one[0]);
// Caveat: this 'orElse' will fail for values that are present but falsy:
console.log("one.orElse('fallback'): " + (one[0] || 'fallback') );
console.log("none.orElse('fallback'): " + (none[0] || 'fallback'));
console.log("Fluent chaining: "+ (
none
.filter(s => s.length > 2)
.map(lodash.upperCase)
[0] || "too short"
));
如果您愿意修改原型,您可以添加一个更健壮的orElse,并根据需要添加语法糖。
- javascript error"java.lang.NullPointerException" i
- {lang:(?:da|en)}在Javascript中做什么
- JSONSTORE Mobilefirst 7.1 error java.lang.NoClassDefFoundErr
- 动态更改语言时,应更新HTML lang属性
- 如何将路径与/lang匹配?使用express中间件
- java.lang.NullPointerException servlet
- 如果网址以“lang=fr”结尾,如何更改网站语言
- 为什么 Servlet.service() for servlet jsp 抛出了异常 java.lang.NullPo
- java.io.IOException: write beyond end of stream OR java.lang
- LiveConnect 无法初始化 firefox 扩展 java.lang.reflect.InvocationTar
- 获取 HTML 元素的隐式 lang 属性
- 从Java Applet调用方法,Javascript返回[Ljava.lang.String;@7ac79dfa
- Javascript closure VS dojo lang.hitch
- Running Java from Nashron JavaScript - Exception java.lang.C
- ClassCastException - JavaScriptObject 不能强制转换为 java.lang.Stri
- Html lang 属性没有出现在页面源代码中
- Ember Optional URL Segments
- 如何改变“;defaultOptions"lang在highCharts中动态显示
- 如何在JavaScript中创建具有lang属性的HTML元素
- JavaScript analog of java.lang.Optional?