yoni-mcscripts-lib
Version:
为 Minecraft Script API 中的部分接口创建了 wrapper,并提供简单的事件管理器和任务管理器,另附有一些便于代码编写的一些小工具。
199 lines (185 loc) • 6.61 kB
text/typescript
function copyPropertiesWithoutOverride(target: {}, src: {}, accessKey: string | symbol, excludeKeys: (string | symbol)[] = []){
if ((typeof accessKey !== "string" && typeof accessKey !== "symbol") || accessKey === ""){
throw new TypeError("accessKey not valid");
}
for (let key of getOwnProperties(src)){
if (key in target || key === accessKey || excludeKeys.includes(key)){
continue;
}
let propertyDescriptor = Object.getOwnPropertyDescriptor(src, key);
if (typeof propertyDescriptor?.value === "function"){
Object.defineProperty(target, key, {
configurable: propertyDescriptor.configurable,
enumerable: propertyDescriptor.enumerable,
writable: false,
value: function (){
const self = this[accessKey];
return self[key].apply(self, arguments);
}
});
} else if (propertyDescriptor !== undefined) {
Object.defineProperty(target, key, {
configurable: propertyDescriptor.configurable,
enumerable: propertyDescriptor.enumerable,
get: function (){
return this[accessKey][key];
},
set: function (value){
this[accessKey][key] = value;
}
});
} else {
if (debug)
throw new ReferenceError(
"Unknown property while copy properties: "
+String(key)
+" don't have a descriptor");
}
}
return target;
}
function assignAllPropertiesWithoutOverride(target: {}, ...srcs: {}[]){
let definedKeys: unknown[] = [];
for (let src of srcs){
for (let key of getProperties(src)){
if (definedKeys.includes(key) || key in target){
continue;
}
definedKeys.push(key);
let propertyDescriptor = Object.getOwnPropertyDescriptor(src, key);
let sa = src;
while (sa !== null && propertyDescriptor === undefined){
propertyDescriptor = Object.getOwnPropertyDescriptor(sa, key);
sa = Object.getPrototypeOf(sa);
}
let value = propertyDescriptor?.value;
if (propertyDescriptor && typeof value === "function"){
Object.defineProperty(target, key, {
configurable: propertyDescriptor.configurable,
enumerable: propertyDescriptor.enumerable,
writable: propertyDescriptor.writable,
value: function (){
return value.apply(src, arguments);
}
});
} else if (propertyDescriptor !== undefined) {
Object.defineProperty(target, key, {
configurable: propertyDescriptor.configurable,
enumerable: propertyDescriptor.enumerable,
get: function () {
// @ts-ignore
return src[key];
},
set: function (value){
// @ts-ignore
src[key] = value;
}
});
} else {
if (debug)
throw new ReferenceError(
"Unknown property while copy properties: "
+String(key)
+" don't have a descriptor");
}
}
}
return target;
}
/**
* 得到一个对象上的所有键值
* @param {any} object
* @param {any} [endPrototype] - 如果键值是继承而来的,从什么原型的位置结束继承,默认为Object.prototype,即从Object原型方法上断开继承
*/
function getKeys(object: any, endPrototype?: {} | null){
if (arguments.length === 1){
endPrototype = Object.prototype;
}
//为了更强的兼容性,使用了var
var sa = object;
var keys = new Set<string>();
var saKeys;
var idx;
var key;
while (sa !== null && sa !== endPrototype){
saKeys = Object.getOwnPropertyNames(sa);
for (idx = 0; idx < saKeys.length; idx ++){
key = saKeys[idx];
if (keys.has(key)){
continue;
}
keys.add(key);
}
sa = Object.getPrototypeOf(sa);
}
return Array.from(keys);
}
/**
* 得到一个对象上的所有属性键值
* @param {any} object
* @param {any} [endPrototype] - 如果键值是继承而来的,从什么原型的位置结束继承,默认为`Object.prototype`,即从Object原型方法上断开继承
*/
function getProperties(object: {}, endPrototype?: {} | null){
if (arguments.length === 1){
endPrototype = Object.prototype;
}
//为了更强的兼容性,使用了var
var sa = object;
var keys = new Set<string|symbol>();
var saKeys;
var idx;
var key;
while (sa !== null && sa !== endPrototype){
saKeys = Object.getOwnPropertyNames(sa);
for (idx = 0; idx < saKeys.length; idx ++){
key = saKeys[idx];
if (keys.has(key)){
continue;
}
keys.add(key);
}
saKeys = Object.getOwnPropertySymbols(sa);
for (idx = 0; idx < saKeys.length; idx ++){
key = saKeys[idx];
if (keys.has(key)){
continue;
}
keys.add(key);
}
sa = Object.getPrototypeOf(sa);
}
return Array.from(keys);
}
function getOwnProperties(object: {}){
return getProperties(object, Object.getPrototypeOf(object));
}
function getOwnKeys(object: {}): (string | symbol)[] {
return getKeys(object, Object.getPrototypeOf(object));
}
function listNotExistingKeys(base: {}, compare: {}){
let o1keys = getKeys(base);
let o2keys = getKeys(compare);
return o1keys.filter((k: string) => {
return o2keys.includes(k) === false;
});
}
const debug = true;
const ObjectUtils = {
copyPropertiesWithoutOverride,
assignAllPropertiesWithoutOverride,
getKeys,
getProperties,
getOwnKeys,
getOwnProperties,
listNotExistingKeys,
};
export {
copyPropertiesWithoutOverride,
assignAllPropertiesWithoutOverride,
getKeys,
getProperties,
getOwnKeys,
getOwnProperties,
listNotExistingKeys,
ObjectUtils,
};