Skip to content

Instantly share code, notes, and snippets.

@wilsoncook
Created December 24, 2020 13:23
Show Gist options
  • Save wilsoncook/5386f49f99b902169f7746e4dec6e6e9 to your computer and use it in GitHub Desktop.
Save wilsoncook/5386f49f99b902169f7746e4dec6e6e9 to your computer and use it in GitHub Desktop.
懒对象:该对象只有在被使用(被访问/设置/删除/遍历属性等)时才会被实例化
/**
* 构建一个懒对象:该对象只有在被使用(被访问/设置/删除/遍历属性等)时才会被实例化
* 其他方案:采用getter方式,如:module.exports = { get XXX() { return new ClsXXX(); } };
* @param factory 实例化函数
*/
function unstable_makeLazyInstance<T>(factory: () => T): T {
let instance: T;
function wrap<H extends (...args: any[]) => any>(handle: H): H {
return ((...args: any[]) => {
if (instance === undefined) instance = factory();
return handle(...args);
}) as H;
}
return new Proxy(Object.create(null), {
ownKeys: wrap(target => {
return Object.getOwnPropertyNames(instance);
}),
has: wrap((target, key) => {
return key in instance;
}),
get: wrap((target, key, receiver) => {
return (instance as any)[key];
}),
set: wrap((target, key, value, receiver) => {
(instance as any)[key] = value;
return true;
}),
defineProperty: wrap((target, key, descriptor) => {
return Object.defineProperty(instance, key, descriptor);
}),
deleteProperty: wrap((target, key) => {
delete (instance as any)[key];
return true;
}),
getOwnPropertyDescriptor: (target, key) => {
return Object.getOwnPropertyDescriptor(instance, key);
},
getPrototypeOf: target => {
return Object.getPrototypeOf(instance);
},
setPrototypeOf: wrap((target, prototype) => {
Object.setPrototypeOf(instance, prototype);
return true;
}),
isExtensible: wrap(target => {
return Object.isExtensible(instance);
}),
preventExtensions: wrap(target => {
// 禁止扩展时,proxy和内部对象应该同时被禁止
// 注:preventExtensions返回的是对象
Object.preventExtensions(target);
Object.preventExtensions(instance);
return true;
}),
}) as T;
}
export { unstable_makeLazyInstance as makeLazyInstance };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment