Skip to content

Instantly share code, notes, and snippets.

@evolify
Last active April 2, 2025 14:54
Show Gist options
  • Save evolify/aafced6efad730ad92cdd82370315ed0 to your computer and use it in GitHub Desktop.
Save evolify/aafced6efad730ad92cdd82370315ed0 to your computer and use it in GitHub Desktop.
web
function myInstanceof(obj, constructor) {
let prototype = constructor.prototype;
let proto = obj.__proto__;
while (true) {
if (proto === null) return false;
if (proto === prototype) return true;
proto = proto.__proto__;
}
}
function prefetch(nodeLists) {
// Exclude slow ECTs < 3g
if (
navigator.connection &&
(navigator.connection.effectiveType === "slow-2g" ||
navigator.connection.effectiveType === "2g")
) {
return;
}
// Exclude low end device which is device with memory <= 2GB
if (navigator.deviceMemory && navigator.deviceMemory <= 2) {
return;
}
const fetchLinkList = {};
const observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
if (!fetchLinkList[entry.target.href]) {
fetchLinkList[entry.target.href] = true;
fetch(entry.target, {
priority: "low",
});
}
observer.unobserve((entry = entry.target));
}
});
});
}
const idleCallback =
window.requestIdleCallback ||
function (cb) {
let start = Date.now();
return setTimeout(function () {
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
},
});
}, 1);
};
idleCallback(function () {
prefetch(nodeLists);
});
const PENDING = "pending"
const FULFILLED = "fulfilled"
const REJECTED = "rejected"
class MyPromise {
#state = PENDING
#result = null
#thenables = []
constructor(executor) {
const resolve = value => {
this.#changeState(FULFILLED, value)
}
const reject = reason => {
this.#changeState(REJECTED, reason)
}
executor(resolve, reject)
}
#changeState(state, result) {
if (this.#state !== PENDING) return
this.#state = state
this.#result = result
this.#run()
}
#handleCallback(callback, resolve, reject) {
if (typeof callback !== "function") {
// 状态穿透
queueMicrotask(() => {
const fn = this.#state === FULFILLED ? resolve : reject
fn(this.#result)
})
return
}
queueMicrotask(() => {
try {
const result = callback(this.#result)
resolve(result)
} catch (error) {
reject(error)
}
})
}
#run() {
if (this.#state === PENDING) return
while (this.#thenables.length) {
const { onFulfilled, onRejected, resolve, reject } =
this.#thenables.shift()
const cb = this.#state === FULFILLED ? onFulfilled : onRejected
this.#handleCallback(cb, resolve, reject)
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this.#thenables.push({
onFulfilled: onFulfilled,
onRejected: onRejected,
resolve,
reject,
})
this.#run()
})
}
catch(onRejected) {
return this.then(null, onRejected)
}
finally(onFinally) {
return this.then(
value => {
onFinally()
return value
},
reason => {
onFinally()
throw reason
}
)
}
}
function render(template, data) {
return template.replace(/\{\{(.+?)\}\}/g, (match, expr) => {
try {
// 使用 Function 构造函数安全执行表达式
return new Function("with(this) { return " + expr + " }").call(data) || '';
// 或者使用 eval
// with (data) {
// return eval(expr);
// }
} catch (e) {
console.error("Error evaluating expression:", expr, e);
return '';
}
});
}
function singleton(Constructor){
let instance = null;
const proxy = new Proxy(Constructor,{
construct(target, args){
if(!instance){
instance = Reflect.construct(target, args);
}
return instance;
}
})
proxy.prototype.constructor = proxy
return proxy
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment