1. 选择器
function selector() {
var ls = document.querySelectorAll(arguments[0]);
if (!ls) return null;
if (ls.length === 1) return ls[0];
return ls;
}
2. 动态计算 rem(适配移动端)
(function () {
var root = document.documentElement;
function init() {
var width = root.clientWidth || window.innerWidth;
width = width < 320 ? 320 : width; // 最小屏幕设定为320px
root.style.fontSize = width >= 640 ? '100px' : (width / 3.75 + 'px'); // 最大屏幕640px;标准375px
document.body.style.fontSize = '16px';
}
window.addEventListener('orientationchange' in window ? 'orientationchange' : 'resize', init, false);
document.addEventListener('DOMContentLoaded', init, false);
})();
3. ES5 模块导出兼容写法
(function (global, factory) {
"use strict"
if (typeof module === "object" && typeof module.exports === "object") {
module.exports = factory(global, true)
} else if (typeof define === 'function' && define.amd) {
define(function () { return factory(global) })
} else {
factory(global)
}
})(typeof window !== "undefined" ? window : this, function (context) {
// 模块内容
});
4. Ajax 封装
GET 请求
/**
* @param {string} url 请求地址
* @param {string} params key=value&key=value 参数字符串
* @param {Function} fn 回调函数
*/
function get(url, params, fn) {
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
if (!xhr) return;
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
fn(xhr.status === 200 ? null : xhr.status, xhr.responseText);
}
};
xhr.open('GET', url + '?' + params, true);
xhr.send(null);
}
POST 请求
/**
* @param {string} url 请求地址
* @param {string|FormData} params 参数
* @param {Function} fn 回调函数
*/
function post(url, params, fn) {
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
if (!xhr) return;
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
fn(xhr.status === 200 ? null : xhr.status, xhr.responseText);
}
};
if (!(params instanceof FormData)) {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
xhr.open('POST', url, true);
xhr.send(params);
}
5. 防抖(Debounce)
/**
* @param {Function} callback
* @param {Number} delay 延时(毫秒)
* @param {Boolean} immediate 立即执行
*/
function Debounce(callback, delay = 1000, immediate = false) {
if (!callback) return;
var timeout, context;
return function () {
context = this;
if (timeout) clearTimeout(timeout);
if (immediate) {
return callback.apply(context, arguments);
} else {
timeout = setTimeout(() => callback.apply(context, arguments), delay);
}
};
}
6. 节流(Throttle)
/**
* @param {Function} callback
* @param {Number} delay 延时(毫秒)
* @param {Boolean} immediate 立即执行
*/
function Throttle(callback, delay = 500, immediate = false) {
if (!callback) return;
let lastTime, timer, context, now;
return function () {
context = this;
now = +new Date();
if (immediate) return callback.apply(context, arguments);
if (lastTime && now < lastTime + delay) {
clearTimeout(timer);
timer = setTimeout(() => {
lastTime = now;
callback.apply(context, arguments);
}, delay);
} else {
lastTime = now;
callback.apply(context, arguments);
}
};
}
7. 圣杯继承模式
const inherit = (Target, Origin) => {
Target.prototype = new Origin();
Target.prototype.constructor = Target;
Target.prototype.$prototype = Origin.prototype;
};
// 示例略
8. 获取滚动条距离
function getScrollOffset() {
if (window.pageXOffset) {
return { x: window.pageXOffset, y: window.pageYOffset };
} else {
return {
x: document.body.scrollLeft + document.documentElement.scrollLeft,
y: document.body.scrollTop + document.documentElement.scrollTop
};
}
}
9. 获取视口尺寸
function getViewportOffset() {
if (window.innerWidth) {
return { w: window.innerWidth, h: window.innerHeight };
} else {
if (document.compatMode === "BackCompat") {
return { w: document.body.clientWidth, h: document.body.clientHeight };
} else {
return { w: document.documentElement.clientWidth, h: document.documentElement.clientHeight };
}
}
}
10. 获取元素任意 CSS 属性
function getStyle(elem, prop) {
return window.getComputedStyle ? window.getComputedStyle(elem, null)[prop] : elem.currentStyle[prop];
}
11. 事件绑定/解绑(兼容 IE)
function addEvent(elem, type, handle) {
if (elem.addEventListener) {
elem.addEventListener(type, handle, false);
} else if (elem.attachEvent) {
elem.attachEvent('on' + type, function () { handle.call(elem); });
} else {
elem['on' + type] = handle;
}
}
function removeEvent(elem, type, handle) {
if (elem.removeEventListener) {
elem.removeEventListener(type, handle, false);
} else if (elem.detachEvent) {
elem.detachEvent('on' + type, handle);
} else {
elem['on' + type] = null;
}
}
12. 阻止事件冒泡
function stopBubble(e) {
if (e && e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
}
13. 判断回文字符串
function isPalindrome(str) {
str = str.replace(/\W/g, '').toLowerCase();
return str === str.split('').reverse().join('');
}
14. 异步加载脚本
function loadScript(url, callback) {
var el = document.createElement('script');
if (el.readyState) {
el.onreadystatechange = function () {
if (el.readyState === 'complete' || 'loaded') callback();
};
} else {
el.onload = callback;
}
el.src = url;
document.body.appendChild(el);
}
15. Cookie 管理
const docCookies = {
get: function (key) {
return decodeURIComponent(
document.cookie.replace(
new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(key).replace(/[-.+*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')
) || ''
},
set: function (key, sValue, vEnd, sPath, sDomain, bSecure) {
if (!key || /^(?:expires|max-age|path|domain|secure)$/i.test(key)) { return false }
let sExpires = ''
if (vEnd) {
switch (vEnd.constructor) {
case Number:
sExpires = vEnd === Infinity ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT' : '; max-age=' + vEnd
break
case String:
sExpires = '; expires=' + vEnd
break
case Date:
sExpires = '; expires=' + vEnd.toUTCString()
break
}
}
const cookieParts = [
encodeURIComponent(key) + '=' + encodeURIComponent(sValue),
sExpires,
sDomain ? '; domain=' + sDomain : '',
sPath ? '; path=' + sPath : '',
bSecure ? '; secure' : ''
].filter(Boolean)
document.cookie = cookieParts.join('')
return true
},
remove: function (key, sPath = '/', sDomain = '.videoseek.ai') {
if (!key || !this.has(key)) { return false }
const cookieParts = [
encodeURIComponent(key) + '=; expires=' + new Date('1970-01-01').toString(),
sDomain ? '; domain=' + sDomain : '',
sPath ? '; path=' + sPath : ''
].filter(Boolean)
document.cookie = cookieParts.join('')
return true
},
has: function (key) {
return (new RegExp('(?:^|;\\s*)' + encodeURIComponent(key).replace(/[-.+*]/g, '\\$&') + '\\s*\\=')).test(document.cookie)
},
keys: function () {
const aKeys = document.cookie.replace(/((?:^|\s*;)[^=]+)(?=;|$)|^\s*|\s*(?:=[^;]*)?(?:1|$)/g, '').split(/\s*(?:=[^;]*)?;\s*/)
for (let nIdx = 0; nIdx < aKeys.length; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]) }
return aKeys
}
}
完整实现见原文。
16. 手写 call / apply / bind
Function.prototype._call = function () {
var args = [].slice.call(arguments)
var ctx = args.shift() || window
ctx.fn = this
var result = ctx.fn(...args)
delete ctx.fn
return result
}
Function.prototype._apply = function () {
var ctx = arguments[0] || window
var args = arguments[1]
ctx.fn = this
args = Array.isArray(args) ? args : []
var result = ctx.fn(...args)
delete ctx.fn
return result
}
Function.prototype._bind = function (otherThis) {
if (typeof this !== 'function') return
var baseArgs = [].slice.call(arguments, 1),
ctx = this,
Temp = function () { },
F = function () {
baseArgs = baseArgs.concat(arguments)
return ctx.apply(
Temp.prototype.isPrototypeOf(this) ? this : otherThis, baseArgs
)
}
if (this.prototype) Temp.prototype = this.prototype
F.prototype = new Temp()
return F
}
17. requestAnimationFrame 兼容
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) { setTimeout(callback, 1000 / 60); };
})();
window.cancelAnimFrame = (function () {
return window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.mozCancelAnimationFrame ||
function (id) { clearTimeout(id); };
})();
18. JSONP 请求
function jsonp(url) {
var el = document.createElement('script');
el.src = url;
document.body.appendChild(el);
}
19. 工具判断函数
判断有值
function isValue(v) {
return !(v === undefined || v === 'undefined' || v === null || v === 'null');
}
获取精确类型
function toType(v) {
return Object.prototype.toString.call(v).replace(/$$|$$/g, '').split(/\s/)[1].toLowerCase();
}
判断数字
function isNumber(v) {
return !isNaN(v);
}
判断 Promise
function isPromise(v) {
return v && typeof v === 'object' && typeof v.then === 'function';
}
判断 DOM 节点
function isDom(v) {
return typeof HTMLElement === 'undefined'
? v && typeof v === 'object' && v.nodeType !== undefined
: v instanceof HTMLElement;
}
判断空值(数组/对象/字符串等)
function isEmpty(v) {
if (Array.isArray(v) || typeof v === 'string') return v.length === 0;
if (v instanceof Map || v instanceof Set) return v.size === 0;
if (v && typeof v === 'object') return Object.keys(v).length === 0;
return false;
}
20. 随机字符串生成
const CHARACTER = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
function anystr(range = 32) {
const r = [];
for (let i = 0; i < range; i++) {
r.push(CHARACTER.charAt(Math.floor(Math.random() * CHARACTER.length)));
}
return r.join('');
}
// 可使用 window.crypto.randomUUID 替代
21. 模板字符串替换
function format(s, args) {
if (!s || !args) return s;
if (Array.isArray(args)) {
args.forEach((v, i) => s = s.replace(new RegExp("({[" + i + "]})", "g"), v));
} else if (typeof args === 'object') {
Object.keys(args).forEach(k => s = s.replace(new RegExp("({" + k + "})", "g"), args[k]));
}
return s;
}
22. 单词首字母大写
function capitalize(v) {
return String(v).toLowerCase().replace(/( |^)[a-z]/g, s => s.toUpperCase());
}
23. 中文 Unicode 编码/解码
const unicode = {
encode(v) {
if (!v) return null;
v = String(v);
const r = [];
for (let i = 0; i < v.length; i++) {
r.push(('00' + v.charCodeAt(i).toString(16)).slice(-4));
}
return '\\u' + r.join('\\u');
},
decode(v) {
return v ? unescape(v.replace(/\\/g, '%')) : null;
}
};
24. URL 参数处理
const urlParams = {
queryString(o) {
if (!o || typeof o !== 'object') return '';
return Object.keys(o).map(k => {
let v = o[k];
if (v === undefined) v = null;
if (v && typeof v === 'object') v = JSON.stringify(v);
return `${k}=${v}`;
}).join('&');
},
get(url, name) {
url = decodeURIComponent(url || location.search).replace(/^\?/, '');
if (!url) return name ? '' : {};
const o = JSON.parse('{"' + url.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}');
return name ? (o[name] === undefined ? '' : o[name]) : o;
}
};
// 可使用 new URLSearchParams 替代
25. 对象操作
浅拷贝合并
function objectMerge() {
const args = [].slice.call(arguments);
const target = Object(args.shift());
args.forEach(o => {
if (!o || typeof o !== 'object') return;
Object.keys(o).forEach(k => {
if (typeof o[k] !== 'undefined') target[k] = o[k];
});
});
return target;
}
粗暴深克隆(不支持函数/循环引用)
该方法有缺陷,“循环引用”(会报错)和函数无法克隆
function objectFormat(o) {
return JSON.parse(JSON.stringify(o || {}));
}
// 可使用 window.structuredClone 或者 lodash.merge 替代
深度克隆(支持嵌套对象/数组)
function deepClone() {
const args = [].slice.call(arguments);
const target = Object(args.shift());
args.forEach(items => {
if (!items || typeof items !== 'object') return;
Object.keys(items).forEach(key => {
if (key === '__proto__') return;
const row = items[key];
if (row === undefined) return;
if (Array.isArray(row)) {
if (!Array.isArray(target[key])) {
target[key] = [...row];
return;
}
row.forEach((col, index) => {
target[key][index] = typeof col === 'object' ? deepClone(target[key][index], col) : col;
});
} else if (typeof row === 'object') {
target[key] = deepClone(target[key] || {}, row);
} else {
target[key] = row;
}
});
});
return target;
}
26. 本地存储封装
const storage = {
session(name, v) {
if (v == null) return sessionStorage.getItem(name);
sessionStorage.setItem(name, typeof v === 'object' ? JSON.stringify(v) : v);
return true;
},
local(name, v) {
if (v == null) return localStorage.getItem(name);
localStorage.setItem(name, typeof v === 'object' ? JSON.stringify(v) : v);
return true;
}
};
27. 倒计时类
class Countdown {
constructor(longtime = 120, delay = 1000, callback = () => {}) {
this.longtime = longtime;
this.delay = delay;
this.fn = callback;
this.stepper = 0;
}
countdown() {
this.fn(this.stepper);
this.timer = setInterval(() => {
if (this.longtime <= this.stepper) return clearInterval(this.timer);
this.stepper++;
this.fn(this.stepper);
}, this.delay);
}
cancel() {
clearInterval(this.timer);
}
}
28. 驼峰与下划线互转
// 下划线 → 驼峰
function toHump(name) {
return name.replace(/\_(\w)/g, (_, letter) => letter.toUpperCase());
}
// 驼峰 → 下划线
function toLine(name) {
return name.replace(/([A-Z])/g, "_$1").toLowerCase();
}
✅ 以上为常用 JavaScript 工具函数整理,适用于兼容性要求高或无构建工具的项目。建议在现代项目中优先使用 ES6+ 语法及模块化方案。