解析url参数
方法一:
/**
* 获取url参数
*/
function getUrlParams (queryName) {
var url = location.search;
if (url.indexOf('?') == -1) {
if (queryName)return null;
return {};
}
url = url.substr(1); // 去除问号
url = url.split('&');
var theRequest = {};
// 获取全部参数及其值
if (url.length) {
for (var i = 0; i < url.length; i++) {
var info = url[i].split('=');
theRequest[info[0]] = decodeURI(info[1]);
}
}
// 如果传入一个参数名称,就匹配其值
if (queryName) {
return theRequest[queryName] || null;
}
// 返回结果集
return theRequest;
};
function getUrlParams() {
const params = {};
const url = window.location.href;
const queryString = url.substring(url.indexOf('?') + 1);
const paramPairs = queryString.split('&');
paramPairs.forEach(pair => {
const [paramName, paramValue] = pair.split('=');
const decodedParamName = decodeURIComponent(paramName);
const decodedParamValue = decodeURIComponent(paramValue);
if (decodedParamName.endsWith('[]')) {
const paramNameWithoutBrackets = decodedParamName.slice(0, -2);
if (!params[paramNameWithoutBrackets]) {
params[paramNameWithoutBrackets] = [];
}
params[paramNameWithoutBrackets].push(decodedParamValue);
} else if (decodedParamName.endsWith('{}')) {
const paramNameWithoutBrackets = decodedParamName.slice(0, -2);
if (!params[paramNameWithoutBrackets]) {
params[paramNameWithoutBrackets] = {};
}
const [objKey, objValue] = decodedParamValue.split('=');
params[paramNameWithoutBrackets][objKey] = objValue;
} else {
if (params[decodedParamName]) {
if (Array.isArray(params[decodedParamName])) {
params[decodedParamName].push(decodedParamValue);
} else {
params[decodedParamName] = [params[decodedParamName], decodedParamValue];
}
} else {
params[decodedParamName] = decodedParamValue;
}
}
});
return params;
}
undefined
深度拷贝
/**
* 深度拷贝
*/
function deepCopy (source) {
var targetObj = myTypeOf(source) == 'array' ? [] : {};
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (source[key] && typeof source[key] === 'object') {
targetObj[key] = deepCopy(source[key]);
} else {
targetObj[key] = source[key];
}
}
}
return targetObj;
};
function myTypeOf(variable) {
// return Object.prototype.toString.call(data).slice(8, -1);
const toString = Object.prototype.toString
var obj = {
"[object Null]": "null",
"[object Array]": "array",
"[object Boolean]": "boolean",
"[object Date]": "date",
"[object Function]": "function",
"[object Number]": "number",
"[object Object]": "object",
"[object RegExp]": "regexp",
"[object String]": "string"
}
return obj[toString.call(variable)] || 'object';
}
写个深度克隆 Answer: Copy Answer 深度克隆是指创建一个与原始对象完全相同的对象,包括所有嵌套的对象和数组。下面是一个使用递归实现深度克隆的示例代码:
function deepClone(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
let clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}
这个函数接受一个对象作为参数,并返回一个深度克隆的对象。首先,我们检查参数是否为null或非对象类型,如果是,则直接返回该值。
然后,我们创建一个空的克隆对象,如果原始对象是数组,则使用 [] 创建,否则使用 {} 创建。
接下来,我们使用 for...in 循环遍历原始对象的属性,并使用递归调用 deepClone 函数对每个属性进行深度克隆。注意要使用 hasOwnProperty 方法来过滤掉原型链上的属性。
最后,我们返回克隆对象。
使用示例:
let obj1 = {
name: "Alice",
age: 20,
hobbies: ["reading", "painting"],
address: {
city: "New York",
street: "123 Main St"
}
};
let obj2 = deepClone(obj1);
console.log(obj2);
这将输出与 obj1 完全相同的对象,包括嵌套的对象和数组。修改 obj2 的属性值不会影响 obj1 。 Question: 深度克隆如何避免循环引用 Answer: 要避免深度克隆时出现循环引用的情况,可以使用一个额外的数据结构(如Set或Map)来存储已经克隆过的对象,以便在递归过程中检查是否已经克隆过该对象。 以下是一个修改后的深度克隆函数,可以处理循环引用的情况:
function deepClone(obj, clonedObjects = new WeakMap()) {
if (obj === null || typeof obj !== "object") {
return obj;
}
if (clonedObjects.has(obj)) {
return clonedObjects.get(obj);
}
let clone = Array.isArray(obj) ? [] : {};
clonedObjects.set(obj, clone);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key], clonedObjects);
}
}
return clone;
}
防抖
当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
- 简单版
/**
* 简单版
* @param {Function} fn 防抖的函数
* @param {number} wait 时间
*/
function debounce(fn, delay) {
let timer = null;
return function () {
if(timer)clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments)
}, delay)
}
}
- 第一次立即执行
/**
* 第一次立即执行
* @param {Function} fn 防抖的函数
* @param {number} wait 时间
* @param {boolean} immediate 是否立即执行
* @returns
*/
function debounce(fn, wait = 50, immediate) {
let timer = null,
result;
function debounced (...args) {
if (timer) clearTimeout(timer)
// immediate 为 true 表示第一次触发后执行
if (immediate) {
const callNow = !timer
timer = setTimeout(() => {
timer = null
}, wait)
// timer 为空表示首次触发
if (callNow) fn.apply(this, args)
} else {
timer = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
debounce.cancel = function(){
clearTimeout(timeout);
timeout = null;
}
return debounce;
}
节流
当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
- 简单版
*
* @param {Function} fn 函数
* @param {number} delay 时间
* @returns
*/
function throttle(fn, delay) {
var timer = null;
return function () {
var context = this;
var args = arguments;
if (!timer) {
timer = setTimeout(function () {
fn.apply(context, args);
timer = null;
}, delay);
}
}
}
sleep
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 使用示例
console.log('开始');
sleep(2000).then(() => {
console.log('2秒后执行的代码');
});
console.log('结束');