【跳槽必备】2023常用手写面试题知识点总结

前言

想想几年前一个月随便投出去一天至少3面试一个月排满面试的场景对于现在已经灭绝了,基本只有外包和驻场有回应,今年很多人都只能猥琐发育,市场上不仅岗位变少,money也少了很多。目前环境的不景气,面试难度也增加了很多,在这样的大环境下也只能不断提升提升自己,时刻警惕被优化的风险。最近刚好复习到手写面试题的基础分享分享给大家伙。

手写实现节流函数

function throttle(func, delay) {let timeoutId; // 用于存储定时器的IDlet lastExecutedTime = 0; // 上次执行的时间戳// 返回一个新的函数作为节流函数return function (...args) {const currentTime = Date.now(); // 当前时间戳// 计算距离上次执行的时间间隔const elapsedTime = currentTime - lastExecutedTime;// 如果距离上次执行的时间间隔大于等于延迟时间,则执行函数if (elapsedTime >= delay) {func.apply(this, args);lastExecutedTime = currentTime; // 更新上次执行的时间戳} else {// 如果距离上次执行的时间间隔小于延迟时间,则设置定时器延迟执行函数clearTimeout(timeoutId);timeoutId = setTimeout(() => {func.apply(this, args);lastExecutedTime = Date.now(); // 更新上次执行的时间戳}, delay - elapsedTime);}};
}

该实现中,throttle 函数接收两个参数:func 是要进行节流处理的函数,delay 是时间间隔,表示在间隔时间内只能执行一次函数。

节流函数返回一个新的函数作为节流后的函数。每次调用节流后的函数时,它会记录当前时间戳,并计算距离上次执行的时间间隔。

如果距离上次执行的时间间隔大于等于延迟时间,则立即执行目标函数,并更新上次执行的时间戳。

如果距离上次执行的时间间隔小于延迟时间,则设置一个定时器,在延迟时间减去时间间隔后执行目标函数,并更新上次执行的时间戳。

这样,可以确保目标函数在一定时间间隔内只能执行一次。

示例,演示如何使用节流函数:

function handleResize() {console.log('Resize event throttled');
}const throttledResize = throttle(handleResize, 200);window.addEventListener('resize', throttledResize);

在示例中,我们定义了一个 handleResize 函数,并使用 throttle 函数对其进行节流处理。然后,我们将节流后的函数 throttledResize 添加到 resize 事件的监听器中。这样,当窗口大小调整时,handleResize 函数只会在每 200 毫秒执行一次,从而减少了函数的执行频率。

手写实现防抖函数

function debounce(func, delay) {let timeoutId; // 用于存储定时器的ID// 返回一个新的函数作为防抖函数return function (...args) {// 如果已经设置了定时器,则清除它if (timeoutId) {clearTimeout(timeoutId);}// 设置新的定时器,延迟执行目标函数timeoutId = setTimeout(() => {func.apply(this, args);}, delay);};
}

该实现中,debounce 函数接收两个参数:func 是要进行防抖处理的函数,delay 是延迟时间,表示在最后一次触发后等待多久执行函数。

防抖函数返回一个新的函数作为防抖后的函数。每次调用防抖后的函数时,它会判断是否已经设置了定时器。如果已经设置了定时器,则清除之前的定时器,以防止函数执行。然后,设置一个新的定时器,延迟执行目标函数。

当最后一次调用防抖后的函数后,如果在延迟时间内没有再次调用,则定时器会触发,执行目标函数 func。这样,可以确保目标函数只在最后一次调用后延迟一段时间执行。

示例,演示如何使用防抖函数:

function handleScroll() {console.log('Scroll event debounced');
}const debouncedScroll = debounce(handleScroll, 200);window.addEventListener('scroll', debouncedScroll);

在示例中,我们定义了一个 handleScroll 函数,并使用 debounce 函数对其进行防抖处理。然后,我们将防抖后的函数 debouncedScroll 添加到 scroll 事件的监听器中。这样,当页面滚动时,handleScroll 函数只会在最后一次滚动后的 200 毫秒延迟执行,从而减少了函数的执行次数。

函数柯里化的实现

function curry(fn) {// 定义内部函数用于递归调用function curried(...args) {// 如果传入的参数数量大于或等于原始函数的参数数量,则直接调用原始函数if (args.length >= fn.length) {return fn(...args);} else {// 如果参数数量不足,则返回一个新的函数,继续等待接收剩余的参数return function (...moreArgs) {return curried(...args, ...moreArgs);};}}return curried; // 返回柯里化后的函数
}

手写实现new操作符

// 自定义new操作符函数:模拟实现new操作符的功能
function myNew(constructorFn, ...args) {// 创建一个空对象,并将其原型设置为构造函数的原型const obj = Object.create(constructorFn.prototype);// 调用构造函数,并将this绑定到新创建的对象上const result = constructorFn.apply(obj, args);// 如果构造函数返回一个对象,则返回该对象;否则返回新创建的对象if (typeof result === 'object' && result !== null) {return result;}return obj;
}// 示例构造函数
function Person(name, age) {this.name = name;this.age = age;
}Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
};// 使用示例
const john = myNew(Person, 'John', 25);
john.sayHello(); // Output: Hello, my name is John and I'm 25 years old.

手写实现instanceof

// 自定义instanceof操作符函数:模拟实现instanceof操作符的功能
function myInstanceOf(obj, constructorFn) {// 获取构造函数的原型对象const prototype = constructorFn.prototype;// 判断对象的原型链中是否存在构造函数的原型while (obj !== null) {if (obj.__proto__ === prototype) {return true;}obj = obj.__proto__;}return false;
}// 示例构造函数
function Person(name, age) {this.name = name;this.age = age;
}// 使用示例
const john = new Person('John', 25);
console.log(myInstanceOf(john, Person)); // Output: true
console.log(myInstanceOf(john, Object)); // Output: true
console.log(myInstanceOf(john, Array)); // Output: false

手写实现Promise:

// 自定义Promise类:模拟实现Promise的基本功能
class MyPromise {constructor(executor) {// Promise的三个状态:pending、fulfilled、rejectedthis.state = 'pending';this.value = undefined;this.reason = undefined;// 用于存储异步操作的回调函数this.onFulfilledCallbacks = [];this.onRejectedCallbacks = [];// 执行executor函数try {executor(this.resolve.bind(this), this.reject.bind(this));} catch (error) {this.reject(error);}}// 解决Promise(状态变为fulfilled)resolve(value) {if (this.state === 'pending') {this.state = 'fulfilled';this.value = value;// 执行所有已注册的fulfilled回调函数this.onFulfilledCallbacks.forEach(callback => callback(this.value));}}// 拒绝Promise(状态变为rejected)reject(reason) {if (this.state === 'pending') {this.state = 'rejected';this.reason = reason;// 执行所有已注册的rejected回调函数this.onRejectedCallbacks.forEach(callback => callback(this.reason));}}// 注册Promise的回调函数then(onFulfilled, onRejected) {if (this.state === 'fulfilled') {onFulfilled(this.value);} else if (this.state === 'rejected') {onRejected(this.reason);} else if (this.state === 'pending') {// 异步操作时,将回调函数存储起来,待异步操作完成后执行this.onFulfilledCallbacks.push(onFulfilled);this.onRejectedCallbacks.push(onRejected);}// 返回新的Promise对象,实现链式调用return this;}
}// 使用示例
const promise = new MyPromise((resolve, reject) => {setTimeout(() => {resolve('Hello, Promise!');}, 2000);
});promise.then(value => {console.log(value); // Output: Hello, Promise!
});

promise.all()的实现

Promise.all 方法用于接收一个 Promise 数组,并在所有 Promise 都成功解析时返回一个包含所有 Promise 结果的新 Promise。如果任何一个 Promise 失败,则返回的 Promise 将立即被拒绝,并带有失败的原因。

function promiseAll(promises) {return new Promise((resolve, reject) => {const results = []; // 用于保存每个Promise的结果let completedPromises = 0; // 已经完成的Promise数量// 遍历传入的Promise数组for (let i = 0; i < promises.length; i++) {// 对每个Promise进行处理promises[i].then((result) => {// 如果Promise成功解决,则将结果保存在相应的位置results[i] = result;completedPromises++;// 当所有Promise都完成时,返回结果if (completedPromises === promises.length) {resolve(results);}}).catch((error) => {// 如果有一个Promise被拒绝,则立即返回拒绝的结果reject(error);});}// 处理空Promise数组的情况if (promises.length === 0) {resolve(results);}});
}

promise.race的实现

Promise.race方法接收一个包含多个Promise的可迭代对象(如数组),并返回一个新的Promise。这个新的Promise将与第一个解决(resolve)或拒绝(reject)的Promise具有相同的解决值或拒绝原因。

function promiseRace(promises) {return new Promise((resolve, reject) => {// 遍历传入的Promise数组for (const promise of promises) {// 对每个Promise进行处理promise.then((result) => {// 如果有一个Promise解决,则使用resolve解决新的Promiseresolve(result);}).catch((error) => {// 如果有一个Promise被拒绝,则使用reject拒绝新的Promisereject(error);});}});
}

Promise.allSettled的实现

Promise.allSettled 方法接收一个包含多个 Promise 的可迭代对象(如数组),并返回一个新的 Promise。这个新的 Promise 在所有传入的 Promise 都解决或拒绝后才会被解决,并返回一个包含每个 Promise 结果的对象数组。对象数组中的每个对象都表示对应的 Promise 结果,包含 status 字段表示 Promise 的状态(“fulfilled” 表示解决,“rejected” 表示拒绝),以及对应的 valuereason 字段表示解决值或拒绝原因。

function promiseAllSettled(promises) {const settledPromises = [];// 遍历传入的 Promise 数组for (const promise of promises) {// 对每个 Promise 进行处理settledPromises.push(Promise.resolve(promise).then((value) => ({status: 'fulfilled',value: value,})).catch((reason) => ({status: 'rejected',reason: reason,})));}return Promise.all(settledPromises);
}

手写实现apply函数:

// 自定义apply函数:模拟实现apply的功能
function myApply(fn, context, args) {if (typeof fn !== 'function') {throw new TypeError('fn must be a function');}// 创建唯一的属性名,用于防止上下文对象属性的覆盖const uniqueKey = Symbol();// 将函数fn作为上下文对象的一个属性context[uniqueKey] = fn;// 调用函数fn,并传入参数数组const result = context[uniqueKey](...args);// 删除添加的属性delete context[uniqueKey];return result;
}// 使用示例
function greet(greeting) {return `${greeting}, ${this.name}!`;
}const person = { name: 'John' };
const greeting = myApply(greet, person, ['Hello']);
console.log(greeting); // Output: Hello, John!

手写实现call函数:

// 自定义call函数:模拟实现call的功能
function myCall(fn, context, ...args) {if (typeof fn !== 'function') {throw new TypeError('fn must be a function');}// 创建唯一的属性名,用于防止上下文对象属性的覆盖const uniqueKey = Symbol();// 将函数fn作为上下文对象的一个属性context[uniqueKey] = fn;// 调用函数fn,并传入参数列表const result = context[uniqueKey](...args);// 删除添加的属性delete context[uniqueKey];return result;
}// 使用示例
function greet(greeting) {return `${greeting}, ${this.name}!`;
}const person = { name: 'John' };
const greeting = myCall(greet, person, 'Hello');
console.log(greeting); // Output: Hello, John!

手写实现bind函数:

// 自定义bind函数:模拟实现bind的功能
function myBind(fn, context, ...args) {if (typeof fn !== 'function') {throw new TypeError('fn must be a function');}return function (...newArgs) {// 将bind时传入的参数和调用时传入的参数合并const allArgs = [...args, ...newArgs];// 调用函数fn,并绑定上下文和参数列表return fn.apply(context, allArgs);};
}// 使用示例
function greet(greeting) {return `${greeting}, ${this.name}!`;
}const person = { name: 'John' };
const greetPerson = myBind(greet, person, 'Hello');
const greeting = greetPerson();
console.log(greeting); // Output: Hello, John!

手写实现深拷贝函数:

function deepClone(obj, hash = new WeakMap()) {if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作if (obj instanceof Date) return new Date(obj);if (obj instanceof RegExp) return new RegExp(obj);// 可能是对象或者普通的值  如果是函数的话是不需要深拷贝if (typeof obj !== "object") return obj;// 是对象的话就要进行深拷贝if (hash.get(obj)) return hash.get(obj);let cloneObj = new obj.constructor();// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身hash.set(obj, cloneObj);for (let key in obj) {if (obj.hasOwnProperty(key)) {// 实现一个递归拷贝cloneObj[key] = deepClone(obj[key], hash);}}return cloneObj;
}
let obj = { name: 1, address: { x: 100 } };
obj.o = obj; // 对象存在循环引用的情况
let d = deepClone(obj);
obj.address.x = 200;
console.log(d);

手写实现数组的find方法:

// 自定义数组的find方法:模拟实现数组的find方法
Array.prototype.myFind = function(callback, thisArg) {// 判断调用myFind方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError('myFind called on non-array object');}// 遍历数组,并调用回调函数查找满足条件的元素for (let i = 0; i < this.length; i++) {// 调用回调函数,并传入当前元素、索引和原数组作为参数const satisfiesCondition = callback.call(thisArg, this[i], i, this);// 如果回调函数返回true,则返回当前元素if (satisfiesCondition) {return this[i];}}// 如果没有满足条件的元素,则返回undefinedreturn undefined;
};// 使用示例
const numbers = [1, 2, 3, 4, 5];// 使用自定义的myFind方法查找数组中第一个偶数
const evenNumber = numbers.myFind(function(num) {return num % 2 === 0;
});console.log(evenNumber); // Output: 2

手写实现数组的every方法:

// 自定义数组的every方法:模拟实现数组的every方法
Array.prototype.myEvery = function(callback, thisArg) {// 判断调用myEvery方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError('myEvery called on non-array object');}// 遍历数组,并调用回调函数判断是否满足条件for (let i = 0; i < this.length; i++) {// 调用回调函数,并传入当前元素、索引和原数组作为参数const satisfiesCondition = callback.call(thisArg, this[i], i, this);// 如果有一个元素不满足条件,则返回falseif (!satisfiesCondition) {return false;}}// 如果所有元素都满足条件,则返回truereturn true;
};// 使用示例
const numbers = [1, 2, 3, 4, 5];// 使用自定义的myEvery方法判断数组是否所有元素都是奇数
const isAllOdd = numbers.myEvery(function(num) {return num % 2 !== 0;
});console.log(isAllOdd); // Output: false

手写实现数组的some方法:

// 自定义数组的some方法:模拟实现数组的some方法
Array.prototype.mySome = function(callback, thisArg) {// 判断调用mySome方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError('mySome called on non-array object');}// 遍历数组,并调用回调函数判断是否满足条件for (let i = 0; i < this.length; i++) {// 调用回调函数,并传入当前元素、索引和原数组作为参数const satisfiesCondition = callback.call(thisArg, this[i], i, this);// 如果回调函数返回true,则返回trueif (satisfiesCondition) {return true;}}// 如果没有满足条件的元素,则返回falsereturn false;
};// 使用示例
const numbers = [1, 2, 3, 4, 5];// 使用自定义的mySome方法判断数组是否存在偶数
const hasEvenNumber = numbers.mySome(function(num) {return num % 2 === 0;
});console.log(hasEvenNumber); // Output: true

手写实现数组的forEach方法:

// 自定义数组的forEach方法:模拟实现数组的forEach方法
Array.prototype.myForEach = function(callback, thisArg) {// 判断调用myForEach方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError('myForEach called on non-array object');}// 遍历数组,并调用回调函数对每个元素进行操作for (let i = 0; i < this.length; i++) {// 调用回调函数,并传入当前元素、索引和原数组作为参数callback.call(thisArg, this[i], i, this);}
};// 使用示例
const numbers = [1, 2, 3, 4, 5];// 使用自定义的myForEach方法对数组进行遍历
numbers.myForEach(function(num) {console.log(num);
});// Output:
// 1
// 2
// 3
// 4
// 5

手写实现数组的reduce方法:

// 自定义数组的reduce方法:模拟实现数组的reduce方法
Array.prototype.myReduce = function(callback, initialValue) {// 判断调用myReduce方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError('myReduce called on non-array object');}// 判断数组是否为空if (this.length === 0 && initialValue === undefined) {throw new TypeError('Reduce of empty array with no initial value');}let accumulator = initialValue !== undefined ? initialValue : this[0];// 遍历数组,并调用回调函数对每个元素进行聚合操作for (let i = initialValue !== undefined ? 0 : 1; i < this.length; i++) {// 调用回调函数,并传入累加器、当前元素、索引和原数组作为参数accumulator = callback(accumulator, this[i], i, this);}// 返回聚合结果return accumulator;
};// 使用示例
const numbers = [1, 2, 3, 4, 5];// 使用自定义的myReduce方法对数组进行求和
const sum = numbers.myReduce(function(acc, num) {return acc + num;
}, 0);console.log(sum); // Output: 15

手写实现数组的filter方法:

// 自定义数组的filter方法:模拟实现数组的filter方法
Array.prototype.myFilter = function(callback, thisArg) {// 判断调用myFilter方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError('myFilter called on non-array object');}// 创建一个新的空数组,用于存储过滤后的结果const filteredArray = [];// 遍历数组,并调用回调函数对每个元素进行过滤for (let i = 0; i < this.length; i++) {// 调用回调函数,并传入当前元素、索引和原数组作为参数const shouldKeep = callback.call(thisArg, this[i], i, this);// 如果回调函数返回true,则将当前元素添加到新数组中if (shouldKeep) {filteredArray.push(this[i]);}}// 返回过滤后的新数组return filteredArray;
};// 使用示例
const numbers = [1, 2, 3, 4, 5];// 使用自定义的myFilter方法对数组进行过滤
const evenNumbers = numbers.myFilter(function(num) {return num % 2 === 0;
});console.log(evenNumbers); // Output: [2, 4]

手写实现数组的map方法:

// 自定义数组的map方法:模拟实现数组的map方法
Array.prototype.myMap = function(callback, thisArg) {// 判断调用myMap方法的对象是否为数组if (!Array.isArray(this)) {throw new TypeError('myMap called on non-array object');}// 创建一个新的空数组,用于存储映射后的结果const mappedArray = [];// 遍历数组,并调用回调函数对每个元素进行映射for (let i = 0; i < this.length; i++) {// 调用回调函数,并传入当前元素、索引和原数组作为参数const mappedValue = callback.call(thisArg, this[i], i, this);// 将映射后的值添加到新数组中mappedArray.push(mappedValue);}// 返回映射后的新数组return mappedArray;
};// 使用示例
const numbers = [1, 2, 3, 4, 5];// 使用自定义的myMap方法对数组进行映射
const doubledNumbers = numbers.myMap(function(num) {return num * 2;
});console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]

在这个示例中,我们手写实现了数组的map方法。我们在Array.prototype对象上添加了一个名为myMap的方法。该方法接受一个回调函数作为参数,用于对数组的每个元素进行映射操作。我们遍历数组的每个元素,并调用回调函数,将当前元素、索引和原数组作为参数传递给回调函数。然后,我们将映射后的值添加到一个新的数组中,并最后返回该数组。

结尾

希望有帮助到的朋友可以帮忙点点赞点点关注是对我最大的支持,同时最近需要跳槽面试的同学需要高频面试宝典大全也可以私信我或者关注公众号【前端嚣张农民】回复->999

同时后面也会更新性能优化相关、vue3的实战项目、nodejs的知识点、包括最近开始使用react项目了,之前一直使用的都是vue和angular,也会更新最近写的项目用nextjs框架,喜欢的可以点点关注不迷路,大家一起学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/107503.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

特种设备怎么运输到国外

特种设备的运输需要考虑多个因素&#xff0c;包括设备的尺寸、重量、敏感度等。以下是一些常用的运输方式&#xff1a; 海运&#xff1a;海运是运输特种设备的主要方式之一&#xff0c;通常采用货运集装箱进行装载。在运输前需要进行妥善包装和固定&#xff0c;以保证设备的安全…

二十六、【颜色调整】

文章目录 1、色相/饱和度2、色彩平衡3、曲线4、可选颜色 1、色相/饱和度 色相其实就是颜色的亮度&#xff0c;就是我们往颜色里边加白色&#xff0c;白色越多颜色越淡。饱和度就是我们往颜色里边加黑色&#xff0c;黑色越多颜色越浓。如下图&#xff0c;我们调整拾色器里边的颜…

2.1 初探大数据

文章目录 零、学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;什么是大数据&#xff08;二&#xff09;大数据的特征1、Volume - 数据量大2、Variety - 数据多样3、Velocity - 数据增速快4、Value - 数据价值低5、Veracity - 数据真实性 &#xff08;三&#xff0…

互联网摸鱼日报(2023-10-11)

互联网摸鱼日报(2023-10-11) 36氪新闻 走向平衡&#xff1a;生成式AI的开源与专有模型之争 麦当劳和可乐们最大的威胁&#xff0c;居然是“减肥药” 束从轩5000万“宴请全国”&#xff0c;老乡鸡会去港股吗&#xff1f; 威马汽车回应破产重整 特斯拉电动皮卡&#xff0c;还…

RabbitMQ消息中间件概述

1.什么是RabbitMQ RabbitMQ是一个由erlang开发的AMQP&#xff08;Advanced Message Queue &#xff09;的开源实现。AMQP 的出现其实也是应了广大人民群众的需求&#xff0c;虽然在同步消息通讯的世界里有很多公开标准&#xff08;如 COBAR的 IIOP &#xff0c;或者是 SOAP 等&…

当出现“无法成功完成操作,因为文件包含病毒或潜在的垃圾软件“时的解决办法

安装补丁或其他安装包时,被系统识别为病毒垃圾 具体解决步骤是: 1.在开始菜单&#xff0c;打开Windows 安全中心 找到主页的病毒和威胁防护 找到管理设置 最后将确认安全的文件或安装包添加到排除项即可

LetCode刷题[简单题](4)顺序链表的顺序合并

在平常的应用场景中很多时候需要将繁杂的信息进行融合&#xff0c;比如零散的时间戳信息进行合并&#xff0c;顺序链表的合并就完美的解决这种问题的痛点。相对于原本的直接合并然后再进行排序&#xff0c;数据结构的复杂度不一样&#xff0c;因此就有类似此题的北京。融合有序…

安装nginx,配置https,并解决403问题

nginx安装 下载nginx&#xff1a;下载地址 上传到/opt目录 解压nginx&#xff0c;并进入解压后到目录 cd /opt tar -zxvf nginx-1.25.2.tar.gz cd nginx-1.25.2编译(with-http_ssl_module为https模块) ./configure --with-http_ssl_module安装 make install默认的安装目录为…

华为eNSP配置专题-VLAN和DHCP的配置

文章目录 华为eNSP配置专题-VLAN和DHCP的配置1、前置环境1.1、宿主机1.2、eNSP模拟器 2、基本环境搭建2.1、基本终端构成和连接 3、VLAN的配置3.1、两台PC先配置静态IP3.2、交换机上配置VLAN 4、接口方式的DHCP的配置4.1、在交换机上开启DHCP4.2、在PC上开启DHCP 5、全局方式的…

【docker】ubuntu下安装

ubuntu下安装docker 卸载原生docker更新软件包安装依赖Docker官方GPG密钥添加软件来源仓库安装docker添加用户组运行docker安装工具重启dockerhelloworld 卸载原生docker $ apt-get remove docker docker-engine docker.io containerd runc更新软件包 apt-get update apt-get…

零售数据分析模板鉴赏-品类销售结构报表

不管是服装零售&#xff0c;还是连锁超市或者其他&#xff0c;只要是零售行业就绕不过商品数据分析&#xff0c;那么商品数据分析该怎么做&#xff1f;奥威BI的零售数据分析方案早早就预设好相关报表模板&#xff0c;点击应用后&#xff0c;一键替换数据源&#xff0c;立得新报…

新版Android Studio搜索不到Lombok以及无法安装Lombok插件的问题

前言 在最近新版本的Android Studio中&#xff0c;使用插件时&#xff0c;在插件市场无法找到Lombox Plugin&#xff0c;具体表现如下图所示&#xff1a; 1、操作步骤&#xff1a; &#xff08;1&#xff09;打开Android Studio->Settings->Plugins&#xff0c;搜索Lom…

【JVM】JVM的内存区域划分

JVM的内存区域划分 堆Java虚拟机栈程序计数器方法区运行时常量池 堆 程序中创建的所有对象都保存在堆中 Java虚拟机栈 Java虚拟机栈的生命周期和线程相同,描述的是Java方法执行的内存模型,每个方法在执行的时候都会同时创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法…

docker下的onlyoffice安装(for seafile)

docker镜像拉取 # 拉取 onlyoffice 镜像docker pull onlyoffice/documentserver 创建所需目录 # 创建几个目录 用于 onlyoffice 的数据卷cd /opt# 建议与 seafile 容器都放在 /opt 目录方便管理mkdir seafile-onlyofficecd seafile-onlyofficemkdir logmkdir datamkdir libmkd…

函数指针解释

函数指针是一种特殊类型的指针&#xff0c;它指向程序中的函数而不是数据。函数指针可以让你在运行时动态地选择调用哪个函数&#xff0c;这在某些编程情景中非常有用&#xff0c;例如回调函数、动态函数调用和函数表驱动的编程。以下是关于函数指针的一些基本概念和用法&#…

git log 美化配置

编辑 vim ~/.gitconfig 添加配置 [alias]lg log --graph --abbrev-commit --decorate --dateformat:%m-%d %H:%M:%S --formatformat:%C(bold blue)%h%C(reset) - %s %C(bold yellow)% d%C(reset) %n %C(dim white) (%ad) - %an%C(reset) --allgit lg 效果

微信小程序------框架

目录 视图层 WXML 数据绑定 列表渲染 条件渲染 模板 wsx事件 逻辑层 生命周期 跳转 视图层 WXML WXML&#xff08;WeiXin Markup Language&#xff09;是框架设计的一套标签语言&#xff0c;结合基础组件、事件系统&#xff0c;可以构建出页面的结构。 先在我们的项目中…

qemu 运行 linux

文章目录 qemu 运行 linuxlinux 内核版本生成配置文件编译设备树编译内核报错与解决运行 linux附录脚本参考 qemu 运行 linux linux 内核版本 linux-6.5.7linux 内核下载地址 https://www.kernel.org/可以在浏览器中点击下载&#xff0c;也可以使用命令行下载 wget https:/…

[23] T^3Bench: Benchmarking Current Progress in Text-to-3D Generation

3D生成蓬勃发展&#xff0c;主流方法通过事例比较和用户调查来评价方法好坏&#xff0c;缺少客观比较指标&#xff1b;本文提出Bench&#xff0c;首次综合比较了不同生成方法&#xff1b;具体来说&#xff0c;本文设计了质量评估&#xff08;Quality Assessment&#xff09;和对…

【Linux】线程的几种退出方法(知识点小记)

线程的几种退出方法&#xff1a; 方法参数介绍头文件功能区别return stutus;status//程序退出的返回值--返回到上一级主调函数 普通线程执行return&#xff0c;只退出当前线程 主函数中执行return&#xff0c;会退出进程&#xff0c;并释放所有线程 exit(int status);status//…