Compare commits

...

20 Commits

Author SHA1 Message Date
yutent 200626dcd9 修正文档 2024-12-27 15:48:24 +08:00
yutent 08e6e27397 fixed 2024-12-27 15:39:22 +08:00
yutent 11d01c7c05 增加.d.ts文件 2024-12-23 11:29:42 +08:00
yutent 22bb09a407 2.4.3:更新文档 2024-09-29 15:08:45 +08:00
yutent e91ce6387a fixed define 2024-09-29 15:05:05 +08:00
yutent 4e459de01c fixed 2024-09-12 10:56:54 +08:00
yutent e5d7304f66 2.4.1 equal -> equals 2024-08-22 18:26:06 +08:00
yutent dab02dbb64 2.4.0 2024-08-22 18:03:35 +08:00
yutent 2a598b2c23 fixed package.json 2024-08-07 11:46:42 +08:00
yutent 61caab972e 2.3.0 2024-08-07 11:45:27 +08:00
yutent be25f2dd4b 增加Obejct.groupBy和Map.groupBy 2024-03-28 18:50:40 +08:00
yutent 0afc54671b fixed 2023-11-06 14:05:13 +08:00
yutent 1285c266c6 2.2.0 2023-06-20 18:50:57 +08:00
yutent c89fff71d9 更新readme 2023-06-20 18:46:30 +08:00
yutent 9fe20a39e2 数组增加一批新原型方法 2023-06-20 18:44:43 +08:00
yutent 0ebe311615 字符串增加版本比较的原型方法 2023-06-20 17:33:35 +08:00
yutent e5097d0b7b fixed Object.prototype.toParams 2023-02-17 12:29:23 +08:00
yutent 1dfd6baf72 更新文档 2022-01-27 15:41:47 +08:00
yutent 5cb13f5d7d update 2022-01-27 15:17:09 +08:00
yutent fcdd7ecd7b update 2022-01-27 15:16:07 +08:00
21 changed files with 734 additions and 253 deletions

14
.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
.Spotlight-V100
.Trashes
.DS_Store
.AppleDouble
.LSOverride
._*
.idea
.vscode
package-lock.json
dist/
node_modules/

13
.npmignore Normal file
View File

@ -0,0 +1,13 @@
.Spotlight-V100
.Trashes
.DS_Store
.AppleDouble
.LSOverride
._*
.idea
.vscode
src/
node_modules/
build.js

View File

@ -1,3 +1,51 @@
2.4.3 / 2024-09-29
==================
* 修复`Object.defineProperty`定义声明
* 增加`Promise.withResolvers`
2.4.2 / 2024-09-12
==================
* 优化字符串转义
2.4.0 / 2024-08-22
==================
* 增加Set的一系列原型方法`union、equal、difference、symmetricDifference、intersection、isSubsetOf、isSupersetOf、isDisjointFrom`
2.3.0 / 2024-08-07
==================
* 增加修复版toFixed
2.2.2 / 2024-03-28
==================
* 增加Obejct.groupBy和Map.groupBy
2.2.1 / 2023-11-06
==================
* 一些小修复
2.2.0 / 2023-07-20
==================
* 数组增加一组原型方法
* 字符串增加版本号大小比较的原型方法
2.1.1 / 2023-02-27
==================
* 修复 Object.prototype.toParams()原型方法
2.1.0 / 2022-01-27
==================
* Array.prototype.item 更名为 Array.prototype.at
* String.prototype.item 更名为 String.prototype.at
* Array 增加findLast()和findLastIndex()原型方法
* Object 增加toParams()原型方法
* String 增加toJson()原型方法
* 重写Array的flat, flatMap原型方法, 性能提升5~10倍(视数据结构而定)
* 使用EsBuild打包代码
2.0.0 / 2020-09-18 2.0.0 / 2020-09-18
================== ==================
* 重构, 分cjs版和esm版。 * 重构, 分cjs版和esm版。

102
Readme.md
View File

@ -1,44 +1,76 @@
![module info](https://nodei.co/npm/es.shim.png?downloads=true&downloadRank=true&stars=true) ![downloads](https://img.shields.io/npm/dt/es.shim.svg)
![version](https://img.shields.io/npm/v/es.shim.svg)
# es.shim # es.shim
> `es.shim` 提供了部分新API, 以及一些常用的扩展方法。具体如下: > `es.shim` 提供了部分新API, 以及一些常用的扩展方法。具体如下:
+ Obejct ```js
* empty() ├── Obejct
│ ├── .empty(any) // 判断对象是否为空对象
│ ├── .groupBy(arr, fn) // 数组分组, 返回分组后的对象
+ Array.prototype │ └── .hasOwn(any, key) // 安全版的 Object.prototype.hasOwnProperty()
* flat() ├── Obejct.prototype
* flatMap() │ └── .toParams() // 把对象转为 key1=value1&key2=value2 格式
* item()
├── Map
│ └── .groupBy(any) // 数组分组, 返回分组后的对象
├── Array.prototype
│ ├── .flat(depth) // 数组降维
│ ├── .flatMap(fn) // 等价于 map(fn) -> flat(1)
│ ├── .at(index) // 读取指定位置的元素, 负值则从后往前读
│ ├── .findLast(fn) // 查找匹配的最后一项
│ ├── .findLastIndex(fn) // 查找匹配的最后一项的索引值
│ ├── .toSorted(fn) // 数组排序, 返回一个副本(不改变原数组)
│ ├── .toReversed(fn) // 反转数组, 同样返回一个副本
│ ├── .toSpliced(fn) // 数组截取, 同样返回副本
│ ├── .with(index, newValue) // 创建一个副本,再修改副本中的元素, 返回副本
│ ├── .group(fn) // 数组分组
│ └── .groupToMap(fn) // 数组分组, 返回Map对象
├── Set.prototype
│ ├── .union(other) // 合并2个集合
│ ├── .equals(other) // 判断2个集合是否一致(仅元素相同, 无关顺序)
│ ├── .difference(other) // 返回不存在于另一个集合的所有元素集合
│ ├── .symmetricDifference(other) // 返回当前集合与给定集合中, 不同时存在的所有元素集合
│ ├── .intersection(other) // 返回共有的元素集合
│ ├── .isSubsetOf(other) // 判断当前集合是否为给定集合的子集
│ ├── .isSupersetOf(other) // 判断当前集合是否为给定集合的超集
│ ├── .isDisjointFrom(other) // 判断当前集合,是否与给定集合完全不重合
├── Date
│ └── .isDate(any) // 判断对象是否为 日期对象
├── Date.prototype
│ ├── .getWeek() // 获取当前是本月第几周
│ ├── .getFullWeek() // 获取当前是本年度第几周
│ └── .format(formatStr) // 把日期按指定格式转换
├── String.prototype
│ ├── .splice(index, len, pad) // 类似数组的splice方法
│ ├── .htmlspecialchars() // 字符串HTML安全转义
│ ├── .tohtml() // htmlspecialchars的还原
│ ├── .xss() // 字符串安全转义
│ ├── .escape() // js特殊字符的转义
│ ├── .at(index) // 读取指定位置的字符, 负值则从后往前读
│ ├── .toJson() // 将url参数转为对象
│ ├── .lt(version) // 判断是否小于目标版本号
│ ├── .lte(version) // 判断是否小于或等于目标版本号
│ ├── .gt(version) // 判断是否大于目标版本号
│ ├── .gte(version) // 判断是否大于或等于目标版本号
│ └── .eq(version) // 判断是否等于目标版本号, 1.0和1.0.0这里会返回true, 而用 == 或 ===, 无法得到正确的结果
├── Number
│ ├── .parse(str) // 将安全范围内的数字字符串转为数字类型
│ └── .fromString(str) // 将字符串转为数字类型
├── Number.prototype
│ └── .toFixed(digits) // 修正版的toFixed
└── Promise
├── .defer() // 创建一个延迟的Promise对象
└── .withResolvers() // 创建一个延迟的Promise对象, 同defer
```
+ Date
* isDate()
+ Date.prototype
* getFullWeek()
* getWeek()
* format()
+ String.prototype
* splice()
* htmlspecialchars()
* tohtml()
* xss()
* escape()
* item()
+ Number
* parse()
* fromString()
+ Promise
* defer()

15
build.js Normal file
View File

@ -0,0 +1,15 @@
/**
* {build}
* @author yutent<yutent.io@gmail.com>
* @date 2021/08/09 11:59:41
*/
const Es = require('esbuild')
Es.build({
entryPoints: ['src/index.mjs'],
outfile: 'dist/index.js',
minify: true,
bundle: true,
target: 'es6'
})

89
index.d.ts vendored Normal file
View File

@ -0,0 +1,89 @@
// String prototype extensions
interface String {
splice(start: number, len: number, fill?: string): string
htmlspecialchars(sign?: 'ENT_QUOTES' | 'ENT_NOQUOTES'): string
tohtml(): string
xss(): string
escape(): string
at(num: number): string
toJson(): Record<string, string>
lt(v: string): boolean
lte(v: string): boolean
gt(v: string): boolean
gte(v: string): boolean
eq(v: string): boolean
}
// Set prototype extensions
interface Set<T> {
union(other: Set<T>): Set<T>
difference(other: Set<T>): Set<T>
symmetricDifference(other: Set<T>): Set<T>
intersection(other: Set<T>): Set<T>
isSubsetOf(other: Set<T>): boolean
isSupersetOf(other: Set<T>): boolean
isDisjointFrom(other: Set<T>): boolean
equals(other: Set<T>): boolean
}
// Promise extensions
interface PromiseConstructor {
defer<T>(): {
promise: Promise<T>
resolve: (value: T | PromiseLike<T>) => void
reject: (reason?: any) => void
}
withResolvers<T>(): {
promise: Promise<T>
resolve: (value: T | PromiseLike<T>) => void
reject: (reason?: any) => void
}
}
// Object extensions
interface ObjectConstructor {
empty(obj: any): boolean
groupBy<T>(arr: T[], fn: (item: T) => string): Record<string, T[]>
hasOwn(obj: any, key: string): boolean
}
interface Object {
toParams(): string
}
// Number extensions
interface NumberConstructor {
parse(val: string | number): string | number
fromString(val: string): number
}
// Map extensions
interface MapConstructor {
groupBy<T, K>(arr: T[], fn: (item: T) => K): Map<K, T[]>
}
// Date prototype extensions
interface Date {
getFullWeek(): number
getWeek(): number
format(str?: string): string
}
// Array prototype extensions
interface Array<T> {
flat(deep?: number, arr?: T[]): T[]
flatMap<U>(callback: (value: T, index: number, array: T[]) => U | U[]): U[]
at(num: number): T
findLast(
predicate: (value: T, index: number, obj: T[]) => boolean
): T | undefined
findLastIndex(
predicate: (value: T, index: number, obj: T[]) => boolean
): number
toSorted(compareFn?: (a: T, b: T) => number): T[]
toReversed(): T[]
toSpliced(start: number, deleteCount?: number, ...items: T[]): T[]
with(index: number, value: T): T[]
group(callback: (value: T) => string): Record<string, T[]>
groupToMap<K>(callback: (value: T) => K): Map<K, T[]>
}

View File

@ -1,13 +0,0 @@
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2017-02-27 18:01:54
*
*/
require('./lib/object')
require('./lib/array.v6')
require('./lib/string')
require('./lib/number')
require('./lib/date')
require('./lib/promise')

View File

@ -1,55 +0,0 @@
/**
* @author yutent<yutent.io@gmail.com>
* @date 2020/09/16 11:54:31
*/
if (!Array.prototype.flat) {
Object.defineProperty(Array.prototype, 'flat', {
value: function(deep = 1) {
var arr = []
if (deep < 0) {
deep = 0
}
deep--
for (let it of this) {
if (it === void 0) {
continue
}
if (Array.isArray(it) && deep >= 0) {
arr = arr.concat(it.flat(deep))
} else {
arr.push(it)
}
}
return arr
},
enumerable: false,
writable: true
})
// 没有flat, 当然也不会flatMap
Object.defineProperty(Array.prototype, 'flatMap', {
value: function(fn) {
return this.map(fn).flat()
},
enumerable: false,
writable: true
})
}
if (!Array.prototype.item) {
Object.defineProperty(Array.prototype, 'item', {
value: function(num) {
var n = +num
if (n < 0) {
n = this.length + n
}
return this[n]
},
enumerable: false,
writable: true
})
}

View File

@ -1,71 +0,0 @@
/**
* @author yutent<yutent.io@gmail.com>
* @date 2020/09/16 11:54:31
*/
// 判断数组是否包含指定元素
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function(val) {
for (let it of this) {
if (it === val) {
return true
}
}
return false
},
enumerable: false,
writable: true
})
}
if (!Array.prototype.flat) {
Object.defineProperty(Array.prototype, 'flat', {
value: function(deep = 1) {
var arr = []
if (deep < 0) {
deep = 0
}
deep--
for (let it of this) {
if (it === void 0) {
continue
}
if (Array.isArray(it) && deep >= 0) {
arr = arr.concat(it.flat(deep))
} else {
arr.push(it)
}
}
return arr
},
enumerable: false,
writable: true
})
// 没有flat, 当然也不会flatMap
Object.defineProperty(Array.prototype, 'flatMap', {
value: function(fn) {
return this.map(fn).flat()
},
enumerable: false,
writable: true
})
}
if (!Array.prototype.item) {
Object.defineProperty(Array.prototype, 'item', {
value: function(num) {
var n = +num
if (n < 0) {
n = this.length + n
}
return this[n]
},
enumerable: false,
writable: true
})
}

View File

@ -1,23 +0,0 @@
/**
* @author yutent<yutent.io@gmail.com>
* @date 2020/09/16 12:07:09
*/
/**
* [ 判断对象/数组是否为空]
* eg.
* Object.empty(obj/arr)
*/
if (!Object.empty) {
Object.defineProperty(Object, 'empty', {
value: function(obj) {
try {
for (let i in obj) {
return false
}
} catch (e) {}
return true
},
enumerable: false
})
}

View File

@ -1,14 +1,30 @@
{ {
"name": "es.shim", "name": "es.shim",
"version": "2.0.2", "version": "2.5.0",
"description": "实现部分新API, 以及一些常用的扩展方法", "description": "实现部分新API, 以及一些常用的扩展方法",
"keyworks": ["es5", "es6", "es7", "polyfill", "extend", "shim"], "keyworks": [
"main": "index.js", "es5",
"exports": { "es6",
"require": "./index.js", "es7",
"import": "./index.mjs" "es2015",
"lodash",
"polyfill",
"extend",
"shim"
],
"main": "dist/index.js",
"types": "index.d.ts",
"files": [
"dist/*",
"index.d.ts"
],
"scripts": {
"start": "node ./build.js"
},
"repository": {
"type": "git",
"url": "git+https://git.wkit.fun/bytedo/es.shim.git"
}, },
"repository": "https://github.com/bytedo/es.shim.git",
"author": "yutent", "author": "yutent",
"license": "MIT" "license": "MIT"
} }

View File

@ -1,12 +1,13 @@
/** /**
* *
* @authors yutent (yutent@doui.cc) * @author yutent<yutent.io@gmail.com>
* @date 2017-02-27 18:01:54 * @date 2022/01/27 15:33:09
*
*/ */
import './lib/object.js' import './lib/set.js'
import './lib/array.js' import './lib/array.js'
import './lib/object.js'
import './lib/map.js'
import './lib/string.js' import './lib/string.js'
import './lib/number.js' import './lib/number.js'
import './lib/date.js' import './lib/date.js'

143
src/lib/array.js Normal file
View File

@ -0,0 +1,143 @@
/**
* @author yutent<yutent.io@gmail.com>
* @date 2020/09/16 11:54:31
*/
/**
* 重写原生的flat方法, 性能提升5~10(看数组的结构)
*/
Object.defineProperty(Array.prototype, 'flat', {
value(deep = 1, arr = []) {
for (let it of this) {
if (Array.isArray(it) && deep > 0) {
it.flat(deep - 1, arr)
} else {
arr.push(it)
}
}
return arr
},
writable: true
})
Object.defineProperty(Array.prototype, 'flatMap', {
value(fn) {
return this.map(fn).flat()
},
writable: true
})
if (!Array.prototype.at) {
Object.defineProperty(Array.prototype, 'at', {
value(num) {
let n = +num
if (n < 0) {
n += this.length
}
return this[n]
}
})
}
if (!Array.prototype.findLast) {
Object.defineProperty(Array.prototype, 'findLast', {
value(fn) {
let num = this.length
while (num > 0) {
let item = this[--num]
if (fn(item, num)) {
return item
}
}
}
})
// 没有findLast也不会有findLastIndex
Object.defineProperty(Array.prototype, 'findLastIndex', {
value(fn) {
let num = this.length
while (num > 0) {
let item = this[--num]
if (fn(item, num)) {
return num
}
}
return -1
}
})
}
// 最新增加的几种方法
if (!Array.prototype.toSorted) {
Object.defineProperty(Array.prototype, 'toSorted', {
value(fn) {
return [...this].sort(fn)
}
})
Object.defineProperty(Array.prototype, 'toReversed', {
value() {
return [...this].reverse()
}
})
Object.defineProperty(Array.prototype, 'toSpliced', {
value(...args) {
return [...this].splice(...args)
}
})
Object.defineProperty(Array.prototype, 'with', {
value(num, val) {
let n = +num
let arr = [...this]
if (n < 0) {
n += arr.length
}
arr[n] = val
return arr
}
})
}
// 数组分组
if (!Array.prototype.group) {
Object.defineProperty(Array.prototype, 'group', {
value(fn) {
let output = {}
if (typeof fn === 'function') {
for (let it of this) {
let key = fn(it)
if (output[key]) {
output[key].push(it)
} else {
output[key] = [it]
}
}
return output
} else {
throw Error('argument callback must be a function.')
}
}
})
Object.defineProperty(Array.prototype, 'groupToMap', {
value(fn) {
let output = new Map()
if (typeof fn === 'function') {
for (let it of this) {
let key = fn(it)
if (output.has(key)) {
output.get(key).push(it)
} else {
output.set(key, [it])
}
}
return output
} else {
throw Error('argument callback must be a function.')
}
}
})
}

View File

@ -6,56 +6,53 @@
//获取当天是本月第几周 //获取当天是本月第几周
if (!Date.isDate) { if (!Date.isDate) {
Object.defineProperty(Date, 'isDate', { Object.defineProperty(Date, 'isDate', {
value: function(obj) { value(obj) {
return obj && typeof obj === 'object' && obj.getTime ? true : false return obj && typeof obj === 'object' && obj.getTime ? true : false
}, }
enumerable: false
}) })
} }
if (!Date.prototype.getFullWeek) { if (!Date.prototype.getFullWeek) {
//获取当天是本年度第几周 //获取当天是本年度第几周
Object.defineProperty(Date.prototype, 'getFullWeek', { Object.defineProperty(Date.prototype, 'getFullWeek', {
value: function() { value() {
let thisYear = this.getFullYear() let thisYear = this.getFullYear()
let that = new Date(thisYear, 0, 1) let that = new Date(thisYear, 0, 1)
let firstDay = that.getDay() let firstDay = that.getDay()
let numsOfToday = (this - that) / 24 / 360 / 1000 let numsOfToday = (this - that) / 24 / 360 / 1000
return Math.ceil((numsOfToday + firstDay) / 7) return Math.ceil((numsOfToday + firstDay) / 7)
}, }
enumerable: false
}) })
//获取当天是本月第几周 //获取当天是本月第几周
Object.defineProperty(Date.prototype, 'getWeek', { Object.defineProperty(Date.prototype, 'getWeek', {
value: function() { value() {
let today = this.getDate() let today = this.getDate()
let thisMonth = this.getMonth() let thisMonth = this.getMonth()
let thisYear = this.getFullYear() let thisYear = this.getFullYear()
let firstDay = new Date(thisYear, thisMonth, 1).getDay() let firstDay = new Date(thisYear, thisMonth, 1).getDay()
return Math.ceil((today + firstDay) / 7) return Math.ceil((today + firstDay) / 7)
}, }
enumerable: false
}) })
} }
//时间格式化 //时间格式化
if (!Date.prototype.format) { if (!Date.prototype.format) {
Object.defineProperty(Date.prototype, 'format', { Object.defineProperty(Date.prototype, 'format', {
value: function(str) { value(str) {
var dt = { let dt = {
fullyear: this.getFullYear(), fullyear: this.getFullYear(),
year: this.getYear(), year: this.getYear(),
fullweek: this.getFullWeek(), fullweek: this.getFullWeek(),
week: this.getWeek(), week: this.getWeek(),
month: this.getMonth() + 1, month: this.getMonth() + 1,
date: this.getDate(), date: this.getDate(),
day: this.getDay() + 1, day: this.getDay(),
hours: this.getHours(), hours: this.getHours(),
minutes: this.getMinutes(), minutes: this.getMinutes(),
seconds: this.getSeconds() seconds: this.getSeconds()
} }
var reg = null let reg = null
str = str || 'Y-m-d H:i:s' str = str || 'Y-m-d H:i:s'
dt.g = dt.hours > 12 ? dt.hours - 12 : dt.hours dt.g = dt.hours > 12 ? dt.hours - 12 : dt.hours
@ -82,7 +79,6 @@ if (!Date.prototype.format) {
str = str.replace(new RegExp(i, 'g'), reg[i]) str = str.replace(new RegExp(i, 'g'), reg[i])
} }
return str return str
}, }
enumerable: false
}) })
} }

13
src/lib/map.js Normal file
View File

@ -0,0 +1,13 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2024/03/28 18:48:08
*/
if (!Map.groupBy) {
Object.defineProperty(Map, 'groupBy', {
value(arr, fn) {
return arr.groupToMap(fn)
}
})
}

View File

@ -3,12 +3,23 @@
* @date 2020/09/16 11:58:40 * @date 2020/09/16 11:58:40
*/ */
// Number.EPSILON
const NATIVE_TO_FIXED = Number.prototype.toFixed
Object.defineProperty(Number.prototype, 'toFixed', {
value(n) {
return NATIVE_TO_FIXED.call(this + Number.EPSILON, n)
},
writable: true
})
// 简单的数字处理 // 简单的数字处理
// 将安全范围内的数字字符串转为数字类型 // 将安全范围内的数字字符串转为数字类型
// 否则转为字符串类型 // 否则转为字符串类型
if (!Number.parse) { if (!Number.parse) {
Object.defineProperty(Number, 'parse', { Object.defineProperty(Number, 'parse', {
value: function(val) { value(val) {
if (typeof val === 'number' || typeof val === 'string') { if (typeof val === 'number' || typeof val === 'string') {
val += '' val += ''
if (val.startsWith('0') && !val.startsWith('0.')) { if (val.startsWith('0') && !val.startsWith('0.')) {
@ -30,17 +41,15 @@ if (!Number.parse) {
} }
} }
return val return val
}, }
enumerable: false
}) })
} }
// 将字符串转为数字类型 // 将字符串转为数字类型
if (!Number.fromString) { if (!Number.fromString) {
Object.defineProperty(Number, 'fromString', { Object.defineProperty(Number, 'fromString', {
value: function(val) { value(val) {
return +val || 0 return +val || 0
}, }
enumerable: false
}) })
} }

60
src/lib/object.js Normal file
View File

@ -0,0 +1,60 @@
/**
* @author yutent<yutent.io@gmail.com>
* @date 2020/09/16 12:07:09
*/
/**
* [ 判断对象/数组是否为空]
* eg.
* Object.empty(obj/arr)
*/
if (!Object.empty) {
Object.defineProperty(Object, 'empty', {
value(obj) {
try {
for (let i in obj) {
return false
}
} catch (e) {}
return true
}
})
}
if (!Object.groupBy) {
Object.defineProperty(Object, 'groupBy', {
value(arr, fn) {
return arr.group(fn)
}
})
}
if (!Object.hasOwn) {
Object.defineProperty(Object, 'hasOwn', {
value(obj, key) {
if (obj === null) {
return false
}
return obj.hasOwnProperty(key)
}
})
}
/**
* 将对象转为url参数字符串
* 注意: 这里不会处理复杂类型, 直接按toString结果拼接
*/
if (!Object.prototype.toParams) {
Object.defineProperty(Object.prototype, 'toParams', {
value() {
let params = ''
for (let k in this) {
if (this[k] === void 0) {
continue
}
params += `&${k}=${this[k]}`
}
return params.slice(1)
}
})
}

View File

@ -4,7 +4,7 @@
*/ */
if (!Promise.defer) { if (!Promise.defer) {
Promise.defer = function() { Promise.defer = function () {
let obj = {} let obj = {}
obj.promise = new Promise((resolve, reject) => { obj.promise = new Promise((resolve, reject) => {
obj.resolve = resolve obj.resolve = resolve
@ -13,3 +13,7 @@ if (!Promise.defer) {
return obj return obj
} }
} }
if (!Promise.withResolvers) {
Promise.withResolvers = Promise.defer
}

110
src/lib/set.js Normal file
View File

@ -0,0 +1,110 @@
/**
* @author yutent<yutent.io@gmail.com>
* @date 2020/09/16 11:54:31
*/
if (!Set.prototype.union) {
// 类似 Array的concat, 合并2个集合, 返回1个新集合, 原集合不发生变化
Object.defineProperty(Set.prototype, 'union', {
value(other) {
let output = new Set([...this])
if (
other.size !== void 0 &&
other.has !== void 0 &&
other.keys !== void 0
) {
for (let it of other.keys()) {
output.add(it)
}
}
return output
}
})
// 同一批 API
// 返回不存在于另一个集合的所有元素集合
Object.defineProperty(Set.prototype, 'difference', {
value(other) {
let output = new Set()
for (let it of this) {
if (!other.has(it)) {
output.add(it)
}
}
return output
}
})
// 返回当前集合与给定集合中, 不同时存在的所有元素集合
Object.defineProperty(Set.prototype, 'symmetricDifference', {
value(other) {
let output = this.difference(other)
for (let it of other) {
if (!this.has(it)) {
output.add(it)
}
}
return output
}
})
// 返回共有的元素集合
Object.defineProperty(Set.prototype, 'intersection', {
value(other) {
let output = new Set()
for (let it of this) {
if (other.has(it)) {
output.add(it)
}
}
return output
}
})
// 判断当前集合是否为给定集合的子集
Object.defineProperty(Set.prototype, 'isSubsetOf', {
value(other) {
for (let it of this) {
if (!other.has(it)) {
return false
}
}
return true
}
})
// 判断当前集合是否为给定集合的超集
Object.defineProperty(Set.prototype, 'isSupersetOf', {
value(other) {
for (let it of other) {
if (!this.has(it)) {
return false
}
}
return true
}
})
// 判断当前集合,是否与给定集合完全不重合
Object.defineProperty(Set.prototype, 'isDisjointFrom', {
value(other) {
for (let it of this) {
if (other.has(it)) {
return false
}
}
return true
}
})
}
// 判断2个集合是否一致(仅元素相同, 无关顺序)
if (!Set.prototype.equals) {
Object.defineProperty(Set.prototype, 'equals', {
value(other) {
return this.size === other.size && this.isSubsetOf(other)
}
})
}

View File

@ -3,10 +3,38 @@
* @date 2020/09/16 12:09:15 * @date 2020/09/16 12:09:15
*/ */
// 版本号比较, 返回 -1, 0, 1
function compare(v1, v2) {
v1 += ''
v2 += ''
if (v1 === v2) {
return 0
} else {
v1 = v1.split('.')
v2 = v2.split('.')
let max = Math.max(v1.length, v2.length)
for (let i = 0; i < max; i++) {
let _1 = +v1[i] || 0,
_2 = +v2[i] || 0
if (_1 > _2) {
return 1
} else if (_1 < _2) {
return -1
}
}
return 0
}
}
//类似于Array 的splice方法 //类似于Array 的splice方法
if (!String.prototype.splice) { if (!String.prototype.splice) {
Object.defineProperty(String.prototype, 'splice', { Object.defineProperty(String.prototype, 'splice', {
value: function(start, len, fill) { value(start, len, fill) {
let length = this.length let length = this.length
let argLen = arguments.length let argLen = arguments.length
@ -35,15 +63,14 @@ if (!String.prototype.splice) {
return strl + fill + strr return strl + fill + strr
} }
}, }
enumerable: false
}) })
} }
//同php的htmlspecialchars函数 //同php的htmlspecialchars函数
if (!String.prototype.htmlspecialchars) { if (!String.prototype.htmlspecialchars) {
Object.defineProperty(String.prototype, 'htmlspecialchars', { Object.defineProperty(String.prototype, 'htmlspecialchars', {
value: function(sign) { value(sign) {
let str = this.replace(/&(?!\w+;)/g, '&amp;') let str = this.replace(/&(?!\w+;)/g, '&amp;')
.replace(/</g, '&lt;') .replace(/</g, '&lt;')
.replace(/>/g, '&gt;') .replace(/>/g, '&gt;')
@ -55,29 +82,28 @@ if (!String.prototype.htmlspecialchars) {
} else { } else {
return str.replace(/"/g, '&quot;') return str.replace(/"/g, '&quot;')
} }
}, }
enumerable: false
}) })
} }
//htmlspecialchars的还原 //htmlspecialchars的还原
if (!String.prototype.tohtml) { if (!String.prototype.tohtml) {
Object.defineProperty(String.prototype, 'tohtml', { Object.defineProperty(String.prototype, 'tohtml', {
value: function() { value() {
return this.replace(/&lt;/gi, '<') return this.replace(/&lt;/gi, '<')
.replace(/&gt;/gi, '>') .replace(/&gt;/gi, '>')
.replace(/&quot;/gi, '"') .replace(/&quot;/gi, '"')
.replace(/&#34;/g, '"')
.replace(/&#39;/g, "'") .replace(/&#39;/g, "'")
.replace(/&amp;/gi, '&') .replace(/&amp;/gi, '&')
}, }
enumerable: false
}) })
} }
//简单的过滤xss //简单的过滤xss
if (!String.prototype.xss) { if (!String.prototype.xss) {
Object.defineProperty(String.prototype, 'xss', { Object.defineProperty(String.prototype, 'xss', {
value: function() { value() {
let str = this.htmlspecialchars('ENT_QUOTES') let str = this.htmlspecialchars('ENT_QUOTES')
str = str str = str
.replace( .replace(
@ -86,31 +112,81 @@ if (!String.prototype.xss) {
) )
.replace(/(%0[0-8bcef])|(%1[0-9a-f])/g, '') .replace(/(%0[0-8bcef])|(%1[0-9a-f])/g, '')
return str return str
}, }
enumerable: false
}) })
} }
// js特殊字符的转义 // js特殊字符的转义
if (!String.prototype.escape) { if (!String.prototype.escape) {
Object.defineProperty(String.prototype, 'escape', { Object.defineProperty(String.prototype, 'escape', {
value: function() { value() {
return this.replace(/('|"|&|\\|\}|\{|\(|\)|;|=|\,|&)/g, '\\$1') return this.replace(/('|"|&|\\|\}|\{|\(|\)|;|=|\,|&)/g, '\\$1')
}, }
enumerable: false
}) })
} }
if (!String.prototype.item) { if (!String.prototype.at) {
Object.defineProperty(String.prototype, 'item', { Object.defineProperty(String.prototype, 'at', {
value: function(num) { value(num) {
var n = +num let n = +num
if (n < 0) { if (n < 0) {
n = this.length + n n += this.length
} }
return this[n] return this[n]
}, }
enumerable: false, })
writable: true }
/**
* 将url参数转为对象
* 注意: 这里不处理同一个参数多次出现的情况, 会直接覆盖
*/
if (!String.prototype.toJson) {
Object.defineProperty(String.prototype, 'toJson', {
value() {
let str = this.replace(/^\?/, '')
let params = decodeURIComponent(str)
.split('&')
.filter(_ => _)
.map(_ => _.split('='))
let obj = {}
for (let it of params) {
obj[it[0]] = it[1] || ''
}
return obj
}
})
}
// 用于版本号的比较
if (!String.prototype.lt) {
Object.defineProperty(String.prototype, 'lt', {
value(v) {
return compare(this, v) === -1
}
})
Object.defineProperty(String.prototype, 'lte', {
value(v) {
return compare(this, v) < 1
}
})
Object.defineProperty(String.prototype, 'gt', {
value(v) {
return compare(this, v) === 1
}
})
Object.defineProperty(String.prototype, 'gte', {
value(v) {
return compare(this, v) > -1
}
})
Object.defineProperty(String.prototype, 'eq', {
value(v) {
return compare(this, v) === 0
}
}) })
} }

4
test/index.js Normal file
View File

@ -0,0 +1,4 @@
require('../dist/index.js')
console.log((1.345).toFixed())
console.log((1.345).toFixed(2))