likes
comments
collection
share

扫盲: Intl 国际化命名空间

作者站长头像
站长
· 阅读数 21

引言

Intl 对象是 ECMAScript 国际化 API 的一个命名空间, 它提供了以下几个功能:

  • 字符串比较
  • 数字格式化
  • 日期时间格式化
  • 相对时间格式化
  • 根据数量获取复数形式
  • 格式化字符串列表
  • 文本分割

一、排序: Intl.Collator

Intl.Collator 是一个构造函数, 实例对象提供一系列的接口, 可根据设置的语言区域对字符串进行比较

  • 语法: new Intl.Collator([locales[, options]])
  • 可选参数 locales 说明: 用于设置国际化语言类型, 是一个 BCP 47 语言标记 的字符串, 或者是一个包括多个语言标记的 数组
  • 可选参数 options 说明: 可选配置, 配置有点多这里就不一一展开, 具体可查阅 MDN-Collator

1.1 三个方法

  1. 实例方法 Intl.Collator.prototype.compare() 根据给定的语言区域, 对给定的两个字符串进行比较, 如下代码所示:
  • 如果第一个字符大于第二个则返回正整数
  • 如果第一个字符小于第二个则返回负整数
  • 如果第一个字符等于第二个则返回数字 0
console.log(new Intl.Collator().compare("2", "1")); // 1, 或一些其他的正值
console.log(new Intl.Collator().compare("1", "2")); // -1, 或一些其他的负值
console.log(new Intl.Collator().compare("1", "1")); // 0
  1. Intl.Collator.prototype.resolvedOptions() 方法返回 Collator 实例对象计算后的所有配置信息
const col = new Intl.Collator('zh')
console.log(col.resolvedOptions())

扫盲: Intl 国际化命名空间

  1. 静态方法 Intl.Collator.supportedLocalesOf() 方法返回一个数组, 该方法从提供的语言区域列表中, 筛选出符合规则或者说支持的语言列表
const locales = ['ban', 'id-u-co-pinyin', 'de-ID'];
const options = { localeMatcher: 'lookup' };

console.log(Intl.Collator.supportedLocalesOf(locales, options));
// ["id-u-co-pinyin", "de-ID"]

1.2 在 Array.prototype.sort() 中使用

方法 Intl.Collator.prototype.compare() 参数和返回值格式, 和 Array.prototype.sort() 方法的函数参数是一致的, 也就是说它能够直接作为 Array.prototype.sort() 参数被使用

['b', 'f', 'a', 'd', 'c', 'e'].sort(new Intl.Collator().compare)
// ['a', 'b', 'c', 'd', 'e', 'f']

1.3 不同 locales 效果

下面我们来看不同 locales 下, 方法 Intl.Collator.prototype.compare() 的一个具体表现, 已知:

  • 在德语(de)中, ä 是排在字母 z 的前面
  • 在瑞典语(sv)中, ä 则是排在字母 z 的后面
// de: 德语
console.log(new Intl.Collator('de').compare('ä', 'z')); // -1
console.log(['a', 'z', 'ä'].sort(new Intl.Collator('de').compare)); // ['a', 'ä', 'z']

// sv: 瑞典语
console.log(new Intl.Collator('sv').compare('ä', 'z')); // 1
console.log(['a', 'z', 'ä'].sort(new Intl.Collator('sv').compare)); // ['a', 'z', 'ä']

1.4 数字字符串排序

开始前我们来看一个经典的 数字字符串 排序问题, 如下代码如果使用 Array.prototype.sort() 直接对 ['15', '2', '100'] 进行排序, 排序结果将会是 ['100', '15', '2'] 而之所以会是这么一个结果, 那是因为在 JS 对于字符串的比较是按位进行对比的, 也就是说会先对比第一位字符、如若相等则继续对比下一位字符...

['15', '2', '100'].sort();    
// 结果是: ['100', '15', '2']

很显然, 大部分情况下上面👆🏻这个排序结果并不是我们期望的一个结果; 对于字符串如果我们期望按照数字来进行排序, 这里可以通过 Intl.Collatornumeric 参数来实现:

['15', '2', '100'].sort(new Intl.Collator(void 0, { numeric: true }).compare);   
// 结果是: ['2', '15', '100']

1.5 中文按照拼音排序

如题, 现在我们有个需求, 需要将一组 中文字符串 按照 中文拼音 进行排序, 如下代码如果我们直接通过 Array.prototype.sort() 得出的结果显然并不能符合我们的一个预期

const list = ['不', '都', '阿', '非', '词']
list.sort() 
// 结果是: ['不', '词', '都', '阿', '非']

但是这里我们如果使用 Intl.Collator 就很容易实现咯, 只需要设置正确的 locales 即可

const list = ['不', '都', '阿', '非', '词']
list.sort(new Intl.Collator('zh').compare) 
// 结果是: ['阿', '不', '词', '都', '非']

二、时间格式化: Intl.DateTimeFormat

Intl.Collator 是一个构造函数, 实例对象提供一系列的接口, 可根据设置的语言区域对时间进行格式化

  • 语法: new Intl.DateTimeFormat([locales[, options]])
  • 可选参数 locales 说明: 用于设置国际化语言类型, 是一个 BCP 47 语言标记的字符串, 或者是一个包括多个语言标记的 数组
  • 可选参数 options 说明: 可选配置, 配置有点多这里就不一一展开, 具体可查阅 MDN-DateTimeFormat
  1. 实例方法 Intl.DateTimeFormat.prototype.format() 可根据设置的语言区域, 对时间参数进行一个格式化
const df = new Intl.DateTimeFormat('zh', {
  year: 'numeric',  
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  hour12: false
})

df.format(new Date()) // '2023/08/22 08:12:41'

参数说明:

  • year: 'numeric' 表示使用数值来表示年份
  • 2-digit 表示使用 2 位数字来进行表示, 如果数值小于 10 则会在前面添加 0
  • hour12: false 表示采用 24 小时制
  1. 实例方法 Intl.DateTimeFormat.prototype.formatToParts() 作用和 format 一致, 只是它返回的是一个对象数组, 对象数组包含了相对时间的一些列值, 拿到该对象后我们可以实现自定义格式化
const df = new Intl.DateTimeFormat('zh', {
  year: 'numeric',  
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  hour12: false
})

df.formatToParts(new Date()) // '2023/08/22 08:12:41'

扫盲: Intl 国际化命名空间

  1. 实例方法 Intl.DateTimeFormat.prototype.formatRange() 可根据设置的语言区域, 将给定的两个日期参数进行格式化
const date1 = new Date(Date.UTC(1906, 0, 10, 10, 0, 0)); 
const date2 = new Date(Date.UTC(1906, 0, 10, 11, 0, 0)); 
const date3 = new Date(Date.UTC(1906, 0, 20, 10, 0, 0)); 

const fmt1 = new Intl.DateTimeFormat("en", {
  year: "2-digit",
  month: "numeric",
  day: "numeric",
  hour: "numeric",
  minute: "numeric",
});

console.log(fmt1.format(date1)); // '1/10/06, 10:00 AM'
console.log(fmt1.formatRange(date1, date2)); // '1/10/06, 10:00 – 11:00 AM'
console.log(fmt1.formatRange(date1, date3)); // '1/10/06, 10:00 AM – 1/20/07, 10:00 AM'

const fmt2 = new Intl.DateTimeFormat("en", {
  year: "numeric",
  month: "short",
  day: "numeric",
});
console.log(fmt2.format(date1)); // 'Jan 10, 1906'
console.log(fmt2.formatRange(date1, date2)); // 'Jan 10, 1906'
console.log(fmt2.formatRange(date1, date3)); // 'Jan 10 – 20, 1906'
  1. 实例方法 Intl.DateTimeFormat.prototype.formatRangeToParts() 作用和 formatRange 一致, 只是它返回的是一个对象数组, 对象数组包含了相对时间的一些列值, 拿到该对象后我们可以实现自定义格式化
const date1 = new Date(Date.UTC(1906, 0, 10, 10, 0, 0));
const date2 = new Date(Date.UTC(1906, 0, 10, 11, 0, 0));

const fmt = new Intl.DateTimeFormat("en", {
  hour: "numeric",
  minute: "numeric",
});

console.log(fmt.formatRange(date1, date2)); // '10:00 – 11:00 AM'

fmt.formatRangeToParts(date1, date2);
// [
//   { type: 'hour',      value: '10',  source: "startRange" },
//   { type: 'literal',   value: ':',   source: "startRange" },
//   { type: 'minute',    value: '00',  source: "startRange" },
//   { type: 'literal',   value: ' – ', source: "shared"     },
//   { type: 'hour',      value: '11',  source: "endRange"   },
//   { type: 'literal',   value: ':',   source: "endRange"   },
//   { type: 'minute',    value: '00',  source: "endRange"   },
//   { type: 'literal',   value: ' ',   source: "shared"     },
//   { type: 'dayPeriod', value: 'AM',  source: "shared"     }
// ]
  1. 实例方法 Intl.DateTimeFormat.prototype.resolvedOptions() 方法返回实例对象计算后的所有配置信息
const df = new Intl.DateTimeFormat('zh')
df.resolvedOptions()

扫盲: Intl 国际化命名空间

  1. 静态方法 Intl.DateTimeFormat.supportedLocalesOf() 方法返回一个数组, 该方法从提供的语言区域列表中, 筛选出符合规则或者说支持的语言列表
const locales = ['ban', 'id-u-co-pinyin', 'de-ID'];
const options = { localeMatcher: 'lookup' };

console.log(Intl.DateTimeFormat.supportedLocalesOf(locales, options));
// ["id-u-co-pinyin", "de-ID"]

三、相对时间格式化 Intl.RelativeTimeFormat

在很多新闻、社区等地方经常可以看到很多相对时间的计算, 比如: 今天、昨天、上周...., 在没有 Intl.RelativeTimeFormat 之前我们可能得通过复杂的时间计算来得到这个相对值, 现在有了它我们就可以很方便的完成相对时间的计算!!! 下面我们来简单了解下 Intl.RelativeTimeFormat 的一个基本使用

Intl.RelativeTimeFormat 是一个构造函数, 实例对象提供一系列的接口, 可根据设置的语言区域对相对时间进行格式化

  • 语法: new Intl.RelativeTimeFormat([locales[, options]])
  • 可选参数 locales 说明: 用于设置国际化语言类型, 是一个 BCP 47 语言标记的字符串, 或者是一个包括多个语言标记的 数组
  • 可选参数 options 说明: 可选配置, 配置有点多这里就不一一展开, 具体可查阅 MDN-RelativeTimeFormat

3.1 四个方法

  1. 实例方法 Intl.RelativeTimeFormat.prototype.format(num, unit) 根据给定的语言区域, 返回一个相对时间, 其中参数 num 是一个具体的整数, unit 则是对应的单位, 可选值有: yearquartermonthweekdayhourminutesecond
const rtf = new Intl.RelativeTimeFormat('zh')
rtf.format(1, 'day') // 1天后
  1. 实例方法 Intl.RelativeTimeFormat.prototype.formatToParts() 作用和 format 一致, 只是它返回的是一个对象数组, 对象数组包含了相对时间的一些列值, 拿到该对象后我们可以实现自定义格式化
const rtf = new Intl.RelativeTimeFormat('zh')
rtf.formatToParts(1, 'day') // 1天后

扫盲: Intl 国际化命名空间

  1. 实例方法 Intl.RelativeTimeFormat.prototype.resolvedOptions() 用于获取当前实例对象的配置信息
const rtf = new Intl.RelativeTimeFormat('zh')
rtf.resolvedOptions()

扫盲: Intl 国际化命名空间

  1. 静态方法 Intl.RelativeTimeFormat.supportedLocalesOf() 方法返回一个数组, 该方法从提供的语言区域列表中, 筛选出符合规则或者说支持的语言列表
const locales = ['ban', 'id-u-co-pinyin', 'de-ID'];
const options = { localeMatcher: 'lookup' };

console.log(Intl.RelativeTimeFormat.supportedLocalesOf(locales, options));
// ["id-u-co-pinyin", "de-ID"]

3.2 更符合本土语言

上文演示 format(1, 'day') 返回的结果是 1天后, 但大部分情况下我们可能更想要得到的结果是 明天; 这里我们可以修改 numeric 配置来实现

const rtf = new Intl.RelativeTimeFormat('zh', {
  numeric: 'auto'
});
rtf.format(0, 'day') // 今天

rtf.format(-1, 'day'); // 昨天
rtf.format(1, 'day'); // 明天

rtf.format(-2, 'day') // 前天
rtf.format(2, 'day') // 后天


rtf.format(0, 'year') // 今年
rtf.format(1, 'year') // 明年
rtf.format(-1, 'year') // 明年

四、数字格式化: Intl.NumberFormat

Intl.NumberFormat 是一个构造函数, 实例对象提供一系列的接口, 可根据设置的语言区域对数字进行格式化

  • 语法: new Intl.NumberFormat([locales[, options]])
  • 可选参数 locales 说明: 用于设置国际化语言类型, 是一个 BCP 47 语言标记的字符串, 或者是一个包括多个语言标记的 数组
  • 可选参数 options 说明: 可选配置, 配置有点多这里就不一一展开, 具体可查阅 MDN-NumberFormat

4.1 六个方法

  1. 实例方法 Intl.NumberFormat.prototype.format, 根据给定的语言区域, 对给定是数字进行格式化
const nf = new Intl.NumberFormat('zh');
console.log(nf.format(654321.987));  // 654,321.987
  1. 实例方法 Intl.NumberFormat.prototype.formatToParts() 作用和 format 一致, 只是它返回的是一个对象数组, 对象数组包含了格式化后各个部分的值, 拿到该对象后我们可以实现自定义格式化
const nf = new Intl.NumberFormat('zh');
nf.formatToParts(12312312313)

扫盲: Intl 国际化命名空间

  1. 实例方法 Intl.NumberFormat.prototype.formatRange() 根据给定的语言区域, 将给定的两个数值参数格式化为一个数值范围字符串
const nf = new Intl.NumberFormat('zh');
nf.formatRange(101231, 1231231.212) // '101,231-1,231,231.212'
  1. 实例方法 Intl.NumberFormat.prototype.formatRangeToParts() 作用和 formatRange 一致, 只是它返回的是一个对象数组, 对象数组包含了格式化后各个部分的值, 拿到该对象后我们可以实现自定义格式化
const nf = new Intl.NumberFormat('zh');
nf.formatRangeToParts(101231, 1231231.212)

扫盲: Intl 国际化命名空间

  1. 实例方法 Intl.NumberFormat.prototype.resolvedOptions() 用于获取当前实例对象的配置信息
const nf = new Intl.NumberFormat('zh');
nf.resolvedOptions()

扫盲: Intl 国际化命名空间

  1. 静态方法 Intl.NumberFormat.supportedLocalesOf() 方法返回一个数组, 该方法从提供的语言区域列表中, 筛选出符合规则或者说支持的语言列表
const locales = ['ban', 'id-u-co-pinyin', 'de-ID'];
const options = { localeMatcher: 'lookup' };

console.log(Intl.RelativeTimeFormat.supportedLocalesOf(locales, options));
// ["id-u-co-pinyin", "de-ID"]

4.2 千位分隔符分隔

在实际开发问题中, 对于较大数值常常需要使用千位分隔符进行分隔, 在日常中我们可能会使用 Number.toLocaleString() 方法来实现

(12345678.231).toLocaleString() // '12,345,678.231'

当然我们这里其实也可以使用 Intl.NumberFormat 来实现

const nf = new Intl.NumberFormat()
nf.format(1234567890.12) // '1,234,567,890.12'

如果只是需要将数字按每 3 位数进行一个分割, 那么 Number.toLocaleString()Intl.NumberFormat 都是可以做到, 但是假设想要按照每 4 位数字进行分割, 那么这里就只能通过 Intl.NumberFormat 来实现了

const nf = new Intl.NumberFormat(void 0, {
  minimumFractionDigits: 4
})
nf.format(1234567890.12) // '1,234,567,890.1200'

这里需要注意的是当小数位数小于 minimumFractionDigits 将会自动补 0

4.3 数字不足位数补 0

有时我们可能需要为数字补全, 比如如果数字小于 10, 如 8 则需要进行补全也就是 08; 面对该需求我们可以使用 ES6 现成的 API padStart() 进行补全

String(1).padStart(2, '0') // '01'

这里除了使用 padStart() 其实使用 Intl.NumberFormat 也是可以实现的

const nf = new Intl.NumberFormat(void 0, {
  minimumIntegerDigits: 2
})

nf.format(8) // '08'

同时, 如果位数较大, 超过了 3 位, 那么为了避免遇到逗号分隔的尴尬, 这里可以设置 useGroupingfalse

new Intl.NumberFormat(void 0, {
  minimumIntegerDigits: 10,
}).format(8) // '0,000,000,008'


new Intl.NumberFormat(void 0, {
  useGrouping: false,
  minimumIntegerDigits: 10,
}).format(8) // '0000000008'

4.4 金额

通过 Intl.NumberFormat 可将数值按照金额进行格式化

new Intl.NumberFormat('zh', {
  style: 'currency', 
  currency: 'CNY',
  currencyDisplay: 'name'
}).format(12345.6789)   // 12,345.68人民币

new Intl.NumberFormat('zh', {
  style: 'currency', 
  currency: 'USD',
  currencyDisplay: 'name'
}).format(12345.6789) // 12,345.68美元

new Intl.NumberFormat('en', {
  style: 'currency', 
  currency: 'USD',
  currencyDisplay: 'name'
}).format(12345.6789) // 12,345.68 US dollars

当然大部分情况下我们可能需要将给定的数字格式化为 ¥ + 数字 或者 $ + 数字 的形式, 那么我们只需要在上面 demo 的基础上去除 currencyDisplay 配置即可

new Intl.NumberFormat('zh', {
  style: 'currency', 
  currency: 'CNY',
}).format(12345.6789)   // ¥12,345.68'

new Intl.NumberFormat('en', {
  style: 'currency', 
  currency: 'USD',
}).format(12345.6789) // $12,345.68

4.5 数字转中文

在时间处理中, 我们都知道 new Date().getDay() 获取到的是数字, 在转换过程中我们可能需要将数字转为中文, 这里我们其实可以借用 Intl.NumberFormat 来实现, 而不是通过创建数字和中文的映射表来实现

const nf = new Intl.NumberFormat('zh-Hans-CN-u-nu-hanidec')
const day = new Date().getDay()
const format = `星期${nf.format(day)}` // 星期六

五、字符串列表格式化: Intl.ListFormat

Intl.ListFormat 是一个构造函数, 实例对象提供一系列的接口, 可根据设置的语言区域对字符串列表进行格式化

  • 语法: new Intl.ListFormat([locales[, options]])
  • 可选参数 locales 说明: 用于设置国际化语言类型, 是一个 BCP 47 语言标记 的字符串, 或者是一个包括多个语言标记的 数组
  • 可选参数 options 说明: 可选配置, 配置有点多这里就不一一展开, 具体可查阅 MDN-ListFormat
  1. 实例方法 Intl.ListFormat.prototype.format() 根据给定的语言区域, 对给定是字符串列表进行格式化
const list = ["Motorcycle", "Bus", "Car"];

new Intl.ListFormat("en", { style: "long", type: "conjunction" }).format(list)
// Motorcycle, Bus and Car

new Intl.ListFormat("en", { style: "short", type: "disjunction" }).format(list)
// Motorcycle, Bus or Car

new Intl.ListFormat("en", { style: "narrow", type: "unit" }).format(list)
// Motorcycle Bus Car

new Intl.ListFormat("zh", { style: "long", type: "conjunction" }).format(list)
// Motorcycle、Bus和Car

new Intl.ListFormat("zh", { style: "short", type: "disjunction" }).format(list)
// Motorcycle、Bus或Car

扫盲: Intl 国际化命名空间

  1. 实例方法 Intl.ListFormat.prototype.formatToParts()format 作用一致, 只不过它返回的是一个对象数组, 包含格式化后的各个部分的内容, 方便我们进行自定义
const list = ["Motorcycle", "Bus", "Car"];

new Intl.ListFormat("en", { style: "long", type: "conjunction" }).formatToParts(list)

扫盲: Intl 国际化命名空间

  1. 实例方法 Intl.ListFormat.prototype.resolvedOptions() 用于获取当前实例对象的配置信息
const lf = new Intl.ListFormat("en", { style: "long", type: "conjunction" })
lf.resolvedOptions()

扫盲: Intl 国际化命名空间

  1. 静态方法 Intl.ListFormat.supportedLocalesOf() 方法返回一个数组, 该方法从提供的语言区域列表中, 筛选出符合规则或者说支持的语言列表
const locales = ['ban', 'id-u-co-pinyin', 'de-ID'];
const options = { localeMatcher: 'lookup' };

console.log(Intl.ListFormat.supportedLocalesOf(locales, options));
// ["id-u-co-pinyin", "de-ID"]

六、复数格式: Intl.PluralRules

Intl.PluralRules 是一个构造函数, 实例对象提供一系列的接口, 可根据设置的语言区域进行一些列复数操作

  • 语法: new Intl.PluralRules([locales[, options]])
  • 可选参数 locales 说明: 用于设置国际化语言类型, 是一个 BCP 47 语言标记 的字符串, 或者是一个包括多个语言标记的 数组
  • 可选参数 options 说明: 可选配置, 配置有点多这里就不一一展开, 具体可查阅 MDN-PluralRules
  1. 实例方法 Intl.PluralRules.prototype.select() 根据给定的语言区域, 对给定的数值格式化为复数形式
const pr = new Intl.PluralRules('en')
pr.select(0); // 'zero'
pr.select(1); // 'one'
pr.select(2); // 'two'
pr.select(6); // 'few'
pr.select(18); // 'many'
  1. 实例方法 Intl.PluralRules.prototype.selectRange() 根据给定的语言区域, 对给定的数值范围将其格式化为复数形式
const pr = new Intl.PluralRules('en')
new Intl.PluralRules("sl").selectRange(102, 201); // 'few'
new Intl.PluralRules("pt").selectRange(102, 102); // 'other'
  1. 实例方法 Intl.PluralRules.prototype.resolvedOptions() 用于获取当前实例对象的配置信息
const pr = new Intl.PluralRules('en')
pr.resolvedOptions()

扫盲: Intl 国际化命名空间

  1. 静态方法 Intl.PluralRules.supportedLocalesOf() 方法返回一个数组, 该方法从提供的语言区域列表中, 筛选出符合规则或者说支持的语言列表
const locales = ['ban', 'id-u-co-pinyin', 'de-ID'];
const options = { localeMatcher: 'lookup' };

console.log(Intl.PluralRules.supportedLocalesOf(locales, options));
// ["id-u-co-pinyin", "de-ID"]

七、文本分割: Intl.Segmenter

Intl.Segmenter 是一个构造函数, 实例对象提供一系列的接口, 可根据设置的语言区域对字符串进行分割

  • 语法: new Intl.Segmenter([locales[, options]])
  • 可选参数 locales 说明: 用于设置国际化语言类型, 是一个 BCP 47 语言标记 的字符串, 或者是一个包括多个语言标记的 数组
  • 可选参数 options 说明: 可选配置, 配置有点多这里就不一一展开, 具体可查阅 MDN-Segmenter
  1. 实例方法 Intl.Segmenter.prototype.segment() 根据给定的语言区域, 对给定的字符串进行分割; 需要注意的是这里返回的是可迭代对象
const segmenterFr = new Intl.Segmenter('fr', { granularity: 'word' });
const res = segmenterFr.segment('Que ma joie demeure')
console.log([...res])

扫盲: Intl 国际化命名空间

  1. 实例方法 Intl.Segmenter.prototype.resolvedOptions() 用于获取当前实例对象的配置信息
const segmenterFr = new Intl.Segmenter('fr')
segmenterFr.resolvedOptions()

扫盲: Intl 国际化命名空间

  1. 静态方法 Intl.Segmenter.supportedLocalesOf() 方法返回一个数组, 该方法从提供的语言区域列表中, 筛选出符合规则或者说支持的语言列表
const locales = ['ban', 'id-u-co-pinyin', 'de-ID'];
const options = { localeMatcher: 'lookup' };

console.log(Intl.Segmenter.supportedLocalesOf(locales, options));
// ["id-u-co-pinyin", "de-ID"]
  1. 和使用 String.prototype.split(' ') 有何区别

如果字符串对应语言是使用空格来分隔单词的, 那么从结束上来看是一样的; 但是如果是其他语言(不是使用空格分个单词)那么使用它们得到结果就不一定是一致的咯, 例如: 日语、中文、泰语、老挝语、高棉语、缅甸语等

const str = "吾輩は猫である。名前はたぬき。";
console.log(str.split(' '))

const segmenterJa = new Intl.Segmenter("ja-JP", { granularity: "word" });
const segments = segmenterJa.segment(str);

console.table([...segments]);

扫盲: Intl 国际化命名空间

八、参考