前端手写综合考题
1 实现一个
// 使用 promise来实现 sleepconst sleep = (time) => {return new Promise(resolve => setTimeout(resolve, time))}sleep(1000).then(() => {// 这里写你的骚操作})
sleep 函数,比如 sleep(1000) 意味着等待1000毫秒
2 给定两个数组,写一个方法来计算它们的交集
例如:给定 nums1 = [1, 2, 2, 1],nums2 = [2, 2],返回 [2, 2]。
function union(arr1, arr2) {return arr1.filter(item => {return arr2.indexOf(item) > -1;})}const a = [1, 2, 2, 1];const b = [2, 3, 2];console.log(union(a, b)); // [2, 2]
3 异步并发数限制
/*** 关键点* 1. new promise 一经创建,立即执行* 2. 使用 Promise.resolve().then 可以把任务加到微任务队列,防止立即执行迭代方法* 3. 微任务处理过程中,产生的新的微任务,会在同一事件循环内,追加到微任务队列里* 4. 使用 race 在某个任务完成时,继续添加任务,保持任务按照最大并发数进行执行* 5. 任务完成后,需要从 doingTasks 中移出*/
4 异步串行 | 异步并行
// 字节面试题,实现一个异步加法
function asyncAdd(a, b, callback) {setTimeout(function () {callback(null, a + b);}, 500);
}// 解决方案
// 1. promisify
const promiseAdd = (a, b) => new Promise((resolve, reject) => {asyncAdd(a, b, (err, res) => {if (err) {reject(err)} else {resolve(res)}})
})// 2. 串行处理
async function serialSum(...args) {return args.reduce((task, now) => task.then(res => promiseAdd(res, now)), Promise.resolve(0))
}// 3. 并行处理
async function parallelSum(...args) {if (args.length === 1) return args[0]const tasks = []for (let i = 0; i < args.length; i += 2) {tasks.push(promiseAdd(args[i], args[i + 1] || 0))}const results = await Promise.all(tasks)return parallelSum(...results)
}// 测试
(async () => {console.log('Running...');const res1 = await serialSum(1, 2, 3, 4, 5, 8, 9, 10, 11, 12)console.log(res1)const res2 = await parallelSum(1, 2, 3, 4, 5, 8, 9, 10, 11, 12)console.log(res2)console.log('Done');
})()
5 实现有并行限制的 Promise 调度器
题目描述:JS 实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有两个
addTask(1000,"1");addTask(500,"2");addTask(300,"3");addTask(400,"4");的输出顺序是:2 3 1 4整个的完整执行流程:一开始1、2两个任务开始执行
500ms时,2任务执行完毕,输出2,任务3开始执行
800ms时,3任务执行完毕,输出3,任务4开始执行
1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
1200ms时,4任务执行完毕,输出4
class Scheduler {constructor(limit) {this.queue = [];this.maxCount = limit;this.runCounts = 0;}add(time, order) {const promiseCreator = () => {return new Promise((resolve, reject) => {setTimeout(() => {console.log(order);resolve();}, time);});};this.queue.push(promiseCreator);}taskStart() {for (let i = 0; i < this.maxCount; i++) {this.request();}}request() {if (!this.queue || !this.queue.length || this.runCounts >= this.maxCount) {return;}this.runCounts++;this.queue.shift()().then(() => {this.runCounts--;this.request();});}
}
const scheduler = new Scheduler(2);
const addTask = (time, order) => {scheduler.add(time, order);
};
addTask(1000, "1");
addTask(500, "2");
addTask(300, "3");
addTask(400, "4");
scheduler.taskStart();
6 图片懒加载
// <img src="default.png" data-src="https://xxxx/real.png">
function isVisible(el) {const position = el.getBoundingClientRect()const windowHeight = document.documentElement.clientHeight// 顶部边缘可见const topVisible = position.top > 0 && position.top < windowHeight;// 底部边缘可见const bottomVisible = position.bottom < windowHeight && position.bottom > 0;return topVisible || bottomVisible;
}function imageLazyLoad() {const images = document.querySelectorAll('img')for (let img of images) {const realSrc = img.dataset.srcif (!realSrc) continueif (isVisible(img)) {img.src = realSrcimg.dataset.src = ''}}
}// 测试
window.addEventListener('load', imageLazyLoad)
window.addEventListener('scroll', imageLazyLoad)
// or
window.addEventListener('scroll', throttle(imageLazyLoad, 1000))
7 实现 getValue/setValue 函数来获取path对应的值
// 示例
var object = { a: [{ b: { c: 3 } }] }; // path: 'a[0].b.c'
var array = [{ a: { b: [1] } }]; // path: '[0].a.b[0]'function getValue(target, valuePath, defaultValue) {}console.log(getValue(object, "a[0].b.c", 0)); // 输出3
console.log(getValue(array, "[0].a.b[0]", 12)); // 输出 1
console.log(getValue(array, "[0].a.b[0].c", 12)); // 输出 12
/*** 测试属性是否匹配*/
export function testPropTypes(value, type, dev) {const sEnums = ['number', 'string', 'boolean', 'undefined', 'function']; // NaNconst oEnums = ['Null', 'Object', 'Array', 'Date', 'RegExp', 'Error'];const nEnums = ['[object Number]','[object String]','[object Boolean]','[object Undefined]','[object Function]','[object Null]','[object Object]','[object Array]','[object Date]','[object RegExp]','[object Error]',];const reg = new RegExp('\\[object (.*?)\\]');// 完全匹配模式,type应该传递类似格式[object Window] [object HTMLDocument] ...if (reg.test(type)) {// 排除nEnums的12种if (~nEnums.indexOf(type)) {if (dev === true) {console.warn(value, 'The parameter type belongs to one of 12 types:number string boolean undefined Null Object Array Date RegExp function Error NaN');}}if (Object.prototype.toString.call(value) === type) {return true;}return false;}
}
const syncVarIterator = {getter: function (obj, key, defaultValue) {// 结果变量const defaultResult = defaultValue === undefined ? undefined : defaultValue;if (testPropTypes(obj, 'Object') === false && testPropTypes(obj, 'Array') === false) {return defaultResult;}// 结果变量,暂时指向obj持有的引用,后续将可能被不断的修改let result = obj;// 得到知道值try {// 解析属性层次序列const keyArr = key.split('.');// 迭代obj对象属性for (let i = 0; i < keyArr.length; i++) {// 如果第 i 层属性存在对应的值则迭代该属性值if (result[keyArr[i]] !== undefined) {result = result[keyArr[i]];// 如果不存在则返回未定义} else {return defaultResult;}}} catch (e) {return defaultResult;}// 返回获取的结果return result;},setter: function (obj, key, val) {// 如果不存在obj则返回未定义if (testPropTypes(obj, 'Object') === false) {return false;}// 结果变量,暂时指向obj持有的引用,后续将可能被不断的修改let result = obj;try {// 解析属性层次序列const keyArr = key.split('.');let i = 0;// 迭代obj对象属性for (; i < keyArr.length - 1; i++) {// 如果第 i 层属性对应的值不存在,则定义为对象if (result[keyArr[i]] === undefined) {result[keyArr[i]] = {};}// 如果第 i 层属性对应的值不是对象(Object)的一个实例,则抛出错误if (!(result[keyArr[i]] instanceof Object)) {throw new Error('obj.' + keyArr.splice(0, i + 1).join('.') + 'is not Object');}// 迭代该层属性值result = result[keyArr[i]];}// 设置属性值result[keyArr[i]] = val;return true;} catch (e) {return false;}},
};
使用promise来实现
创建 enhancedObject 函数
const enhancedObject = (target) =>new Proxy(target, {get(target, property) {if (property in target) {return target[property];} else {return searchFor(property, target); //实际使用时要对value值进行复位}},});let value = null;
function searchFor(property, target) {for (const key of Object.keys(target)) {if (typeof target[key] === "object") {searchFor(property, target[key]);} else if (typeof target[property] !== "undefined") {value = target[property];break;}}return value;
}
使用 enhancedObject 函数
const data = enhancedObject({user: {name: "test",settings: {theme: "dark",},},
});console.log(data.user.settings.theme); // dark
console.log(data.theme); // dark
8 创建10个标签,点击的时候弹出来对应的序号
var a
for(let i=0;i<10;i++){a=document.createElement('a')a.innerHTML=i+'<br>'a.addEventListener('click',function(e){console.log(this) //this为当前点击的<a>e.preventDefault() //如果调用这个方法,默认事件行为将不再触发。//例如,在执行这个方法后,如果点击一个链接(a标签),浏览器不会跳转到新的 URL 去了。我们可以用 event.isDefaultPrevented() 来确定这个方法是否(在那个事件对象上)被调用过了。alert(i)})const d=document.querySelector('div')d.appendChild(a) //append向一个已存在的元素追加该元素。
}
9.版本号排序的方法
题目描述:有一组版本号如下 ['0.1.1', '2.3.3', '0.302.1', '4.2', '4.3.5', '4.3.4.5']。现在需要对其进行排序,排序的结果为 ['4.3.5','4.3.4.5','2.3.3','0.302.1','0.1.1']
- 对版本号数组进行排序,可以使用数组的sort方法,传入一个比较函数用于比较版本号大小。比较函数接受两个参数,表示要比较的两个版本号。
- 在比较函数中,需要将版本号字符串按照.分割成数字数组,然后依次比较每一位数字的大小。如果某一位数字不同,则直接返回差值,否则比较下一位数字,直到所有数字都比较完毕。
- 注意对版本号长度不同的情况进行处理,可以在比较函数中使用数组的fill方法将版本号长度补齐为相同的长度,然后再进行比较。
const versions = ['0.1.1', '2.3.3', '0.302.1', '4.2', '4.3.5', '4.3.4.5'];versions.sort((a, b) => {const arrA = a.split('.').map(Number);const arrB = b.split('.').map(Number);const len = Math.max(arrA.length, arrB.length);arrA.length = len;arrB.length = len;for (let i = 0; i < len; i++) {if (arrA[i] !== arrB[i]) {return arrB[i] - arrA[i];}}return 0;
});console.log(versions); // ['4.3.5', '4.3.4.5', '2.3.3', '0.302.1', '0.1.1']
10 请实现 DOM2JSON 一个函数,可以把一个 DOM 节点输出 JSON 的格式
<div><span><a></a></span><span><a></a><a></a></span>
</div>把上面dom结构转成下面的JSON格式{tag: 'DIV',children: [{tag: 'SPAN',children: [{ tag: 'A', children: [] }]},{tag: 'SPAN',children: [{ tag: 'A', children: [] },{ tag: 'A', children: [] }]}]
}
function dom2Json(domtree) {let obj = {};obj.tag = domtree.tagName;obj.children = [];domtree.childNodes.forEach((child) => obj.children.push(dom2Json(child)));return obj;
}
11 分片思想解决大数据量渲染问题
let ul = document.getElementById("container");
// 插入十万条数据
let total = 100000;
// 一次插入 20 条
let once = 20;
//总页数
let page = total / once;
//每条记录的索引
let index = 0;
//循环加载数据
function loop(curTotal, curIndex) {if (curTotal <= 0) {return false;}//每页多少条let pageCount = Math.min(curTotal, once);window.requestAnimationFrame(function () {for (let i = 0; i < pageCount; i++) {let li = document.createElement("li");li.innerText = curIndex + i + " : " + ~~(Math.random() * total);ul.appendChild(li);}loop(curTotal - pageCount, curIndex + pageCount);});
}
loop(total, index);
12 实现一个add方法完成两个大数相加
// 题目
let a = "9007199254740991";
let b = "1234567899999999999";function add(a ,b){//...
}
function add(a ,b){//取两个数字的最大长度let maxLength = Math.max(a.length, b.length);//用0去补齐长度a = a.padStart(maxLength , 0);//"0009007199254740991"b = b.padStart(maxLength , 0);//"1234567899999999999"//定义加法过程中需要用到的变量let t = 0;let f = 0; //"进位"let sum = "";for(let i=maxLength-1 ; i>=0 ; i--){t = parseInt(a[i]) + parseInt(b[i]) + f;f = Math.floor(t/10);sum = t%10 + sum;}if(f!==0){sum = '' + f + sum;}return sum;
}
13 怎么在制定数据源里面生成一个长度为 n 的不重复随机数组 能有几种方法 时间复杂度多少(字节)
第一版 时间复杂度为 O(n^2)function getTenNum(testArray, n) {let result = [];for (let i = 0; i < n; ++i) {const random = Math.floor(Math.random() * testArray.length);const cur = testArray[random];if (result.includes(cur)) {i--;break;}result.push(cur);}return result;
}
const testArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
const resArr = getTenNum(testArray, 10);
第二版 标记法 / 自定义属性法 时间复杂度为 O(n)function getTenNum(testArray, n) {let hash = {};let result = [];let ranNum = n;while (ranNum > 0) {const ran = Math.floor(Math.random() * testArray.length);if (!hash[ran]) {hash[ran] = true;result.push(ran);ranNum--;}}return result;
}
const testArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
const resArr = getTenNum(testArray, 10);
第三版 交换法 时间复杂度为 O(n)
function getTenNum(testArray, n) {const cloneArr = [...testArray];let result = [];for (let i = 0; i < n; i++) {debugger;const ran = Math.floor(Math.random() * (cloneArr.length - i));result.push(cloneArr[ran]);cloneArr[ran] = cloneArr[cloneArr.length - i - 1];}return result;
}
const testArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
const resArr = getTenNum(testArray, 14);
14 查找数组公共前缀(美团)
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。示例 1:输入:strs = ["flower","flow","flight"]
输出:"fl"示例 2:输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
const longestCommonPrefix = function (strs) {const str = strs[0];let index = 0;while (index < str.length) {const strCur = str.slice(0, index + 1);for (let i = 0; i < strs.length; i++) {if (!strs[i] || !strs[i].startsWith(strCur)) {return str.slice(0, index);}}index++;}return str;
};
15 判断括号字符串是否有效(小米)
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。示例 1:输入:s = "()"
输出:true示例 2:输入:s = "()[]{}"
输出:true示例 3:输入:s = "(]"
输出:false
const isValid = function (s) {if (s.length % 2 === 1) {return false;}const regObj = {"{": "}","(": ")","[": "]",};let stack = [];for (let i = 0; i < s.length; i++) {if (s[i] === "{" || s[i] === "(" || s[i] === "[") {stack.push(s[i]);} else {const cur = stack.pop();if (s[i] !== regObj[cur]) {return false;}}}if (stack.length) {return false;}return true;
};
16 实现一个padStart()或padEnd()的polyfil
String.prototype.padStart和String.prototype.padEnd是ES8中新增的方法,允许将空字符串或其他字符串添加到原始字符串的开头或结尾。我们先看下使用语法:
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'// 1. 若是输入的目标长度小于字符串原本的长度则返回字符串本身
'xxx'.padStart(2, 's') // 'xxx'// 2. 第二个参数的默认值为 " ",长度是为1的
// 3. 而此参数可能是个不确定长度的字符串,若是要填充的内容达到了目标长度,则将不要的部分截取
'xxx'.padStart(5, 'sss') // ssxxx// 4. 可用来处理日期、金额格式化问题
'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
String.prototype.myPadStart = function (targetLen, padString = " ") {if (!targetLen) {throw new Error('请输入需要填充到的长度');}let originStr = String(this); // 获取到调用的字符串, 因为this原本是String{},所以需要用String转为字符串let originLen = originStr.length; // 调用的字符串原本的长度if (originLen >= targetLen) return originStr; // 若是 原本 > 目标 则返回原本字符串let diffNum = targetLen - originLen; // 10 - 6 // 差值for (let i = 0; i < diffNum; i++) { // 要添加几个成员for (let j = 0; j < padString.length; j++) { // 输入的padString的长度可能不为1if (originStr.length === targetLen) break; // 判断每一次添加之后是否到了目标长度originStr = `${padString[j]}${originStr}`;}if (originStr.length === targetLen) break;}return originStr;
}
console.log('xxx'.myPadStart(16))
console.log('xxx'.padStart(16))
17 设计一个方法提取对象中所有value大于2的键值对并返回最新的对象
var obj = { a: 1, b: 3, c: 4 }
foo(obj) // { b: 3, c: 4 }
var obj = { a: 1, b: 3, c: 4 }
function foo (obj) {return Object.fromEntries(Object.entries(obj).filter(([key, value]) => value > 2))
}
var obj2 = foo(obj) // { b: 3, c: 4 }
console.log(obj2)
// ES8中 Object.entries()的作用:
var obj = { a: 1, b: 2 }
var entries = Object.entries(obj); // [['a', 1], ['b', 2]]
// ES10中 Object.fromEntries()的作用:
Object.fromEntries(entries); // { a: 1, b: 2 }
18 实现一个拖拽
<style>html, body {margin: 0;height: 100%;}#box {width: 100px;height: 100px;background-color: red;position: absolute;top: 100px;left: 100px;}
</style>
<div id="box"></div>
window.onload = function () {var box = document.getElementById('box');box.onmousedown = function (ev) {var oEvent = ev || window.event; // 兼容火狐,火狐下没有window.eventvar distanceX = oEvent.clientX - box.offsetLeft; // 鼠标到可视区左边的距离 - box到页面左边的距离var distanceY = oEvent.clientY - box.offsetTop;document.onmousemove = function (ev) {var oEvent = ev || window.event;var left = oEvent.clientX - distanceX;var top = oEvent.clientY - distanceY;if (left <= 0) {left = 0;} else if (left >= document.documentElement.clientWidth - box.offsetWidth) {left = document.documentElement.clientWidth - box.offsetWidth;}if (top <= 0) {top = 0;} else if (top >= document.documentElement.clientHeight - box.offsetHeight) {top = document.documentElement.clientHeight - box.offsetHeight;}box.style.left = left + 'px';box.style.top = top + 'px';}box.onmouseup = function () {document.onmousemove = null;box.onmouseup = null;}}
}
基于Promise.all实现Ajax的串行和并行
- 串行:请求是异步的,需要等待上一个请求成功,才能执行下一个请求
- 并行:同时发送多个请求「
HTTP请求可以同时进行,但是JS的操作都是一步步的来的,因为JS是单线程」,等待所有请求都成功,我们再去做什么事情?
Promise.all并发限制及async-pool的应用
并发限制指的是,每个时刻并发执行的promise数量是固定的,最终的执行结果还是保持与原来的
const delay = function delay(interval) {return new Promise((resolve, reject) => {setTimeout(() => {// if (interval === 1003) reject('xxx');resolve(interval);}, interval);});
};
let tasks = [() => {return delay(1000);
}, () => {return delay(1003);
}, () => {return delay(1005);
}, () => {return delay(1002);
}, () => {return delay(1004);
}, () => {return delay(1006);
}];/* Promise.all(tasks.map(task => task())).then(results => {console.log(results);
}); */let results = [];
asyncPool(2, tasks, (task, next) => {task().then(result => {results.push(result);next();});
}, () => {console.log(results);
});
20 修改嵌套层级很深对象的 key
// 有一个嵌套层次很深的对象,key 都是 a_b 形式 ,需要改成 ab 的形式,注意不能用递归。const a = {a_y: {a_z: {y_x: 6},b_c: 1}
}
// {
// ay: {
// az: {
// yx: 6
// },
// bc: 1
// }
// }
const regularExpress = (obj) => {try {const str = JSON.stringify(obj).replace(/_/g, "");return JSON.parse(str);} catch (error) {return obj;}
};;
const recursion = (obj) => {const keys = Object.keys(obj);keys.forEach((key) => {const newKey = key.replace(/_/g, "");obj[newKey] = recursion(obj[key]);delete obj[key];});return obj;
};
相关文章:
前端手写综合考题
1 实现一个 // 使用 promise来实现 sleepconst sleep (time) > {return new Promise(resolve > setTimeout(resolve, time))}sleep(1000).then(() > {// 这里写你的骚操作}) sleep 函数,比如 sleep(1000) 意味着等待1000毫秒 2 给定两个数组,…...
数据结构-排序
本节目标: 1.排序的概念及其运用 2.常见排序算法的实现 3.排序算法复杂度及稳定性分析 1.排序的概念及其应用 1.1排序的概念 排序就是按照某个我们设定的关键字,或者关键词,递增或者递减,完成这样的操作就是排序。 1.2排…...
ROS话题通信自定义+发布订阅代码--03
话题通信自定义msg 在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味…...
【MySQL】实验七 视图
文章目录 1. 建立city值为上海、北京的顾客视图2. 建立城市为上海的客户2016年的订单信息视图3. SQL视图:建立视图AVG_CJ4. SQL视图:建立视图IS_STUDENT5. SQL视图:建立视图CJ_STUDENT6. SQL视图:根据视图CJ_STUDENT创建视图CJ_TJ1. 建立city值为上海、北京的顾客视图 建立…...
Linux常见操作命令【三】
一、系统资源 1.1 ps(process staus) ps -ef e显示所有进程、f全格式 ps -aux 显示所有包含其他使用者的进程 ps -ef | grep CCC 查找含有CCC进程的格式 ps -u username 显示指定进程用户信息1.2 kill kill 12345 杀死进程12345 kill -KILL…...
C-关键字(下)
文章目录循环控制switch-case-break-defaultdo-while-forgetchar()break-continuegotovoidvoid*returnconstconst修饰变量const修饰数组const修饰指针指针补充const 修饰返回值volatilestruct柔型数组union联合体联合体空间开辟问题利用联合体的性质,判断机器是大端还是小端enu…...
关于电商商品数据API接口列表,你想知道的(详情页、Sku信息、商品描述、评论问答列表)
目录 一、商品数据API接口列表 二、商品详情数据API调用代码item_get 三、获取sku详细信息item_sku 四、获得淘宝商品评论item_review 五、数据说明文档 进入 一、商品数据API接口列表 二、商品详情数据API调用代码item_get <?php// 请求示例 url 默认请求参数已经URL…...
232:vue+openlayers选择左右两部分的地图,不重复,横向卷帘
第232个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers项目中自定义js实现横向卷帘。这个示例中从左右两个选择框中来选择不同的地图,做了不重复的处理,即同一个数组,两部分根据选择后的状态做disabled处理,避免重复选择。 直接复制下面的 vue+openlayers…...
溯源取证-内存取证 高难度篇
今天的场景依然是windows场景,只不过此次场景分为两个镜像,本次学习主要学习如何晒别钓鱼邮件、如何提取钓鱼邮件、如何修复损坏的恶意文件、如何提取DLL动态链接库文件 本次需要使用的工具: volatility_2.6_lin64_standalone readpst clams…...
JAVA语言中的代理模式
代理可以进一步划分为静态代理和动态代理,代理模式在实际的生活中场景很多,例如中介、律师、代购等行业,都是简单的代理逻辑,在这个模式下存在两个关键角色: 目标对象角色:即代理对象所代表的对象。 代理…...
最后一步:渲染和绘制
浏览器的工作步骤如下: URL>字符流>词(token)流>DOM树(不含样式信息的 DOM)>DOM树CSS规则(含样式信息的 DOM)>根据样式信息,计算了每个元素的位置和大小>根据这些…...
C++类和对象终章——友元函数 | 友元类 | 内部类 | 匿名对象 | 关于拷贝对象时一些编译器优化
文章目录💐专栏导读💐文章导读🌷友元🌺概念🌺友元函数🍁友元函数的重要性质🌺友元类🍁友元类的重要性质🌷内部类(不常用)🌺内部类的性…...
拼多多按关键字搜索商品 API
一、拼多多平台优势: 1、独创拼团模式 拼团拼单是拼多多独创的营销模式,其特点是基于人脉社交的裂变传播,非常具有传播性。 由于本身走低价路线,加上拼单折扣,商品的分享和人群裂变效果非常明显,电商前期…...
全链路日志追踪
背景 最近线上的日志全局追踪 traceId 不好使了,不同请求经常出现重复的 traceId,或者通过某个请求的 traceId 追踪搜索,检索出了与该请求完全不相干的日志。我领导叫我去排查解决这个问题,这里我把我排查的过程思路以及如何解决…...
ZYNQ:【1】深入理解PS端的TTC定时器(Part1:原理+官方案例讲解)
碎碎念:好久不见,甚是想念!本期带来的是有关ZYNQ7020的内容,我们知道ZYNQ作为一款具有硬核的SOC,PS端很强大,可以更加便捷地实现一些算法验证。本文具体讲解一下里面的TTC定时器,之后发布的Part…...
蓝牙设备如何自定义UUID
如何自定义UUID 所有 BLE 自定义服务和特性必须使用 128 位 UUID 来识别,并且要确保基本 UUID 与 BLE 定义的基本 UUID(00000000-0000-1000-8000-00805F9B34FB)不一样。基本 UUID 是一个 128 位的数值,根据该值可定义标准UUID&am…...
好看的html登录界面,
界面效果: 代码: <!DOCTYPE html> <html><head><title>Login Page</title><style>body {background-color: #f2f2f2;font-family: Arial, sans-serif;}form {background-color: #fff;border-radius: 5px;box-shado…...
Java模拟星空
目录 前言 JavaFX基础 1. GraphicsContext 2. AnimationTimer 代码实现 完整代码 前言 看了Python模拟星空很漂亮,Java也应该必须有一个! 环境:只需要JDK1.8就好!不需要外部包!!! Jav…...
YGG 代表 Web3 Gaming 参加 2023 年游戏开发者大会
Yield Guild Games(YGG)在 2023 年 3 月 20 日至 24 日在加州旧金山举行的游戏开发者大会(GDC)上大显身手,这是游戏开发者的重要交流学习活动。虽然 GDC 本身提供了多种多样的活动,包括讲座、小组讨论、圆桌…...
水库安全运行智慧管理平台解决方案筑牢防汛“安全墙”
解决方案 水库安全运行智慧管理系统解决方案,系统主要由降雨量监测站、水库水位监测站、大坝安全监测中的渗流量、渗流压力和变形监测站及视频和图像监测站等站点组成,同时建立规范、统一的监测平台,集数据传输、信息共享、数据储存于一体&a…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能
指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...
Copilot for Xcode (iOS的 AI辅助编程)
Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…...
