百度前端必会手写面试题整理
请实现一个 add 函数,满足以下功能
add(1); // 1
add(1)(2); // 3
add(1)(2)(3);// 6
add(1)(2, 3); // 6
add(1, 2)(3); // 6
add(1, 2, 3); // 6
function add(...args) {// 在内部声明一个函数,利用闭包的特性保存并收集所有的参数值let fn = function(...newArgs) {return add.apply(null, args.concat(newArgs))}// 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回fn.toString = function() {return args.reduce((total,curr)=> total + curr)}return fn
}
考点:
- 使用闭包, 同时要对JavaScript 的作用域链(原型链)有深入的理解
- 重写函数的
toSting()
方法
// 测试,调用toString方法触发求值add(1).toString(); // 1
add(1)(2).toString(); // 3
add(1)(2)(3).toString();// 6
add(1)(2, 3).toString(); // 6
add(1, 2)(3).toString(); // 6
add(1, 2, 3).toString(); // 6
判断是否是电话号码
function isPhone(tel) {var regx = /^1[34578]\d{9}$/;return regx.test(tel);
}
解析 URL Params 为对象
let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';
parseParam(url)
/* 结果
{ user: 'anonymous',id: [ 123, 456 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型city: '北京', // 中文需解码enabled: true, // 未指定值得 key 约定为 true
}
*/
function parseParam(url) {const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中let paramsObj = {};// 将 params 存到对象中paramsArr.forEach(param => {if (/=/.test(param)) { // 处理有 value 的参数let [key, val] = param.split('='); // 分割 key 和 valueval = decodeURIComponent(val); // 解码val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key,则添加一个值paramsObj[key] = [].concat(paramsObj[key], val);} else { // 如果对象没有这个 key,创建 key 并设置值paramsObj[key] = val;}} else { // 处理没有 value 的参数paramsObj[param] = true;}})return paramsObj;
}
数组去重
const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}];
// => [1, '1', 17, true, false, 'true', 'a', {}, {}]
方法一:利用Set
const res1 = Array.from(new Set(arr));
方法二:两层for循环+splice
const unique1 = arr => {let len = arr.length;for (let i = 0; i < len; i++) {for (let j = i + 1; j < len; j++) {if (arr[i] === arr[j]) {arr.splice(j, 1);// 每删除一个树,j--保证j的值经过自加后不变。同时,len--,减少循环次数提升性能len--;j--;}}}return arr;
}
方法三:利用indexOf
const unique2 = arr => {const res = [];for (let i = 0; i < arr.length; i++) {if (res.indexOf(arr[i]) === -1) res.push(arr[i]);}return res;
}
当然也可以用include、filter,思路大同小异。
方法四:利用include
const unique3 = arr => {const res = [];for (let i = 0; i < arr.length; i++) {if (!res.includes(arr[i])) res.push(arr[i]);}return res;
}
方法五:利用filter
const unique4 = arr => {return arr.filter((item, index) => {return arr.indexOf(item) === index;});
}
方法六:利用Map
const unique5 = arr => {const map = new Map();const res = [];for (let i = 0; i < arr.length; i++) {if (!map.has(arr[i])) {map.set(arr[i], true)res.push(arr[i]);}}return res;
}
Function.prototype.bind
Function.prototype.bind = function(context, ...args) {if (typeof this !== 'function') {throw new Error("Type Error");}// 保存this的值var self = this;return function F() {// 考虑new的情况if(this instanceof F) {return new self(...args, ...arguments)}return self.apply(context, [...args, ...arguments])}
}
深拷贝
递归的完整版本(考虑到了Symbol属性):
const cloneDeep1 = (target, hash = new WeakMap()) => {// 对于传入参数处理if (typeof target !== 'object' || target === null) {return target;}// 哈希表中存在直接返回if (hash.has(target)) return hash.get(target);const cloneTarget = Array.isArray(target) ? [] : {};hash.set(target, cloneTarget);// 针对Symbol属性const symKeys = Object.getOwnPropertySymbols(target);if (symKeys.length) {symKeys.forEach(symKey => {if (typeof target[symKey] === 'object' && target[symKey] !== null) {cloneTarget[symKey] = cloneDeep1(target[symKey]);} else {cloneTarget[symKey] = target[symKey];}})}for (const i in target) {if (Object.prototype.hasOwnProperty.call(target, i)) {cloneTarget[i] =typeof target[i] === 'object' && target[i] !== null? cloneDeep1(target[i], hash): target[i];}}return cloneTarget;
}
参考 前端进阶面试题详细解答
实现节流函数(throttle)
防抖函数原理:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
// 手写简化版
// 节流函数
const throttle = (fn, delay = 500) => {let flag = true;return (...args) => {if (!flag) return;flag = false;setTimeout(() => {fn.apply(this, args);flag = true;}, delay);};
};
适用场景:
- 拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动
- 缩放场景:监控浏览器resize
- 动画场景:避免短时间内多次触发动画引起性能问题
手写 bind 函数
bind 函数的实现步骤:
- 判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
- 保存当前函数的引用,获取其余传入参数值。
- 创建一个函数返回
- 函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
// bind 函数实现
Function.prototype.myBind = function(context) {// 判断调用对象是否为函数if (typeof this !== "function") {throw new TypeError("Error");}// 获取参数var args = [...arguments].slice(1),fn = this;return function Fn() {// 根据调用方式,传入不同绑定值return fn.apply(this instanceof Fn ? this : context,args.concat(...arguments));};
};
实现数组的filter方法
Array.prototype._filter = function(fn) {if (typeof fn !== "function") {throw Error('参数必须是一个函数');}const res = [];for (let i = 0, len = this.length; i < len; i++) {fn(this[i]) && res.push(this[i]);}return res;
}
实现Promise
var PromisePolyfill = (function () {// 和reject不同的是resolve需要尝试展开thenable对象function tryToResolve (value) {if (this === value) {// 主要是防止下面这种情况// let y = new Promise(res => setTimeout(res(y)))throw TypeError('Chaining cycle detected for promise!')}// 根据规范2.32以及2.33 对对象或者函数尝试展开// 保证S6之前的 polyfill 也能和ES6的原生promise混用if (value !== null &&(typeof value === 'object' || typeof value === 'function')) {try {// 这里记录这次then的值同时要被try包裹// 主要原因是 then 可能是一个getter, 也也就是说// 1. value.then可能报错// 2. value.then可能产生副作用(例如多次执行可能结果不同)var then = value.then// 另一方面, 由于无法保证 then 确实会像预期的那样只调用一个onFullfilled / onRejected// 所以增加了一个flag来防止resolveOrReject被多次调用var thenAlreadyCalledOrThrow = falseif (typeof then === 'function') {// 是thenable 那么尝试展开// 并且在该thenable状态改变之前this对象的状态不变then.bind(value)(// onFullfilledfunction (value2) {if (thenAlreadyCalledOrThrow) returnthenAlreadyCalledOrThrow = truetryToResolve.bind(this, value2)()}.bind(this),// onRejectedfunction (reason2) {if (thenAlreadyCalledOrThrow) returnthenAlreadyCalledOrThrow = trueresolveOrReject.bind(this, 'rejected', reason2)()}.bind(this))} else {// 拥有then 但是then不是一个函数 所以也不是thenableresolveOrReject.bind(this, 'resolved', value)()}} catch (e) {if (thenAlreadyCalledOrThrow) returnthenAlreadyCalledOrThrow = trueresolveOrReject.bind(this, 'rejected', e)()}} else {// 基本类型 直接返回resolveOrReject.bind(this, 'resolved', value)()}}function resolveOrReject (status, data) {if (this.status !== 'pending') returnthis.status = statusthis.data = dataif (status === 'resolved') {for (var i = 0; i < this.resolveList.length; ++i) {this.resolveList[i]()}} else {for (i = 0; i < this.rejectList.length; ++i) {this.rejectList[i]()}}}function Promise (executor) {if (!(this instanceof Promise)) {throw Error('Promise can not be called without new !')}if (typeof executor !== 'function') {// 非标准 但与Chrome谷歌保持一致throw TypeError('Promise resolver ' + executor + ' is not a function')}this.status = 'pending'this.resolveList = []this.rejectList = []try {executor(tryToResolve.bind(this), resolveOrReject.bind(this, 'rejected'))} catch (e) {resolveOrReject.bind(this, 'rejected', e)()}}Promise.prototype.then = function (onFullfilled, onRejected) {// 返回值穿透以及错误穿透, 注意错误穿透用的是throw而不是return,否则的话// 这个then返回的promise状态将变成resolved即接下来的then中的onFullfilled// 会被调用, 然而我们想要调用的是onRejectedif (typeof onFullfilled !== 'function') {onFullfilled = function (data) {return data}}if (typeof onRejected !== 'function') {onRejected = function (reason) {throw reason}}var executor = function (resolve, reject) {setTimeout(function () {try {// 拿到对应的handle函数处理this.data// 并以此为依据解析这个新的Promisevar value = this.status === 'resolved'? onFullfilled(this.data): onRejected(this.data)resolve(value)} catch (e) {reject(e)}}.bind(this))}// then 接受两个函数返回一个新的Promise// then 自身的执行永远异步与onFullfilled/onRejected的执行if (this.status !== 'pending') {return new Promise(executor.bind(this))} else {// pendingreturn new Promise(function (resolve, reject) {this.resolveList.push(executor.bind(this, resolve, reject))this.rejectList.push(executor.bind(this, resolve, reject))}.bind(this))}}// for prmise A+ testPromise.deferred = Promise.defer = function () {var dfd = {}dfd.promise = new Promise(function (resolve, reject) {dfd.resolve = resolvedfd.reject = reject})return dfd}// for prmise A+ testif (typeof module !== 'undefined') {module.exports = Promise}return Promise
})()PromisePolyfill.all = function (promises) {return new Promise((resolve, reject) => {const result = []let cnt = 0for (let i = 0; i < promises.length; ++i) {promises[i].then(value => {cnt++result[i] = valueif (cnt === promises.length) resolve(result)}, reject)}})
}PromisePolyfill.race = function (promises) {return new Promise((resolve, reject) => {for (let i = 0; i < promises.length; ++i) {promises[i].then(resolve, reject)}})
}
滚动加载
原理就是监听页面滚动事件,分析clientHeight、scrollTop、scrollHeight三者的属性关系。
window.addEventListener('scroll', function() {const clientHeight = document.documentElement.clientHeight;const scrollTop = document.documentElement.scrollTop;const scrollHeight = document.documentElement.scrollHeight;if (clientHeight + scrollTop >= scrollHeight) {// 检测到滚动至页面底部,进行后续操作// ...}
}, false);
判断对象是否存在循环引用
循环引用对象本来没有什么问题,但是序列化的时候就会发生问题,比如调用JSON.stringify()
对该类对象进行序列化,就会报错: Converting circular structure to JSON.
下面方法可以用来判断一个对象中是否已存在循环引用:
const isCycleObject = (obj,parent) => {const parentArr = parent || [obj];for(let i in obj) {if(typeof obj[i] === 'object') {let flag = false;parentArr.forEach((pObj) => {if(pObj === obj[i]){flag = true;}})if(flag) return true;flag = isCycleObject(obj[i],[...parentArr,obj[i]]);if(flag) return true;}}return false;
}const a = 1;
const b = {a};
const c = {b};
const o = {d:{a:3},c}
o.c.b.aa = a;console.log(isCycleObject(o)
查找有序二维数组的目标值:
var findNumberIn2DArray = function(matrix, target) {if (matrix == null || matrix.length == 0) {return false;}let row = 0;let column = matrix[0].length - 1;while (row < matrix.length && column >= 0) {if (matrix[row][column] == target) {return true;} else if (matrix[row][column] > target) {column--;} else {row++;}}return false;
};
二维数组斜向打印:
function printMatrix(arr){let m = arr.length, n = arr[0].lengthlet res = []// 左上角,从0 到 n - 1 列进行打印for (let k = 0; k < n; k++) {for (let i = 0, j = k; i < m && j >= 0; i++, j--) {res.push(arr[i][j]);}}// 右下角,从1 到 n - 1 行进行打印for (let k = 1; k < m; k++) {for (let i = k, j = n - 1; i < m && j >= 0; i++, j--) {res.push(arr[i][j]);}}return res
}
实现日期格式化函数
输入:
dateFormat(new Date('2020-12-01'), 'yyyy/MM/dd') // 2020/12/01
dateFormat(new Date('2020-04-01'), 'yyyy/MM/dd') // 2020/04/01
dateFormat(new Date('2020-04-01'), 'yyyy年MM月dd日') // 2020年04月01日
const dateFormat = (dateInput, format)=>{var day = dateInput.getDate() var month = dateInput.getMonth() + 1 var year = dateInput.getFullYear() format = format.replace(/yyyy/, year)format = format.replace(/MM/,month)format = format.replace(/dd/,day)return format
}
字符串出现的不重复最长长度
用一个滑动窗口装没有重复的字符,枚举字符记录最大值即可。用 map 维护字符的索引,遇到相同的字符,把左边界移动过去即可。挪动的过程中记录最大长度:
var lengthOfLongestSubstring = function (s) {let map = new Map();let i = -1let res = 0let n = s.lengthfor (let j = 0; j < n; j++) {if (map.has(s[j])) {i = Math.max(i, map.get(s[j]))}res = Math.max(res, j - i)map.set(s[j], j)}return res
};
手写 Promise
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";function MyPromise(fn) {// 保存初始化状态var self = this;// 初始化状态this.state = PENDING;// 用于保存 resolve 或者 rejected 传入的值this.value = null;// 用于保存 resolve 的回调函数this.resolvedCallbacks = [];// 用于保存 reject 的回调函数this.rejectedCallbacks = [];// 状态转变为 resolved 方法function resolve(value) {// 判断传入元素是否为 Promise 值,如果是,则状态改变必须等待前一个状态改变后再进行改变if (value instanceof MyPromise) {return value.then(resolve, reject);}// 保证代码的执行顺序为本轮事件循环的末尾setTimeout(() => {// 只有状态为 pending 时才能转变,if (self.state === PENDING) {// 修改状态self.state = RESOLVED;// 设置传入的值self.value = value;// 执行回调函数self.resolvedCallbacks.forEach(callback => {callback(value);});}}, 0);}// 状态转变为 rejected 方法function reject(value) {// 保证代码的执行顺序为本轮事件循环的末尾setTimeout(() => {// 只有状态为 pending 时才能转变if (self.state === PENDING) {// 修改状态self.state = REJECTED;// 设置传入的值self.value = value;// 执行回调函数self.rejectedCallbacks.forEach(callback => {callback(value);});}}, 0);}// 将两个方法传入函数执行try {fn(resolve, reject);} catch (e) {// 遇到错误时,捕获错误,执行 reject 函数reject(e);}
}MyPromise.prototype.then = function(onResolved, onRejected) {// 首先判断两个参数是否为函数类型,因为这两个参数是可选参数onResolved =typeof onResolved === "function"? onResolved: function(value) {return value;};onRejected =typeof onRejected === "function"? onRejected: function(error) {throw error;};// 如果是等待状态,则将函数加入对应列表中if (this.state === PENDING) {this.resolvedCallbacks.push(onResolved);this.rejectedCallbacks.push(onRejected);}// 如果状态已经凝固,则直接执行对应状态的函数if (this.state === RESOLVED) {onResolved(this.value);}if (this.state === REJECTED) {onRejected(this.value);}
};
将js对象转化为树形结构
// 转换前:
source = [{id: 1,pid: 0,name: 'body'}, {id: 2,pid: 1,name: 'title'}, {id: 3,pid: 2,name: 'div'}]
// 转换为:
tree = [{id: 1,pid: 0,name: 'body',children: [{id: 2,pid: 1,name: 'title',children: [{id: 3,pid: 1,name: 'div'}]}}]
代码实现:
function jsonToTree(data) {// 初始化结果数组,并判断输入数据的格式let result = []if(!Array.isArray(data)) {return result}// 使用map,将当前对象的id与当前对象对应存储起来let map = {};data.forEach(item => {map[item.id] = item;});// data.forEach(item => {let parent = map[item.pid];if(parent) {(parent.children || (parent.children = [])).push(item);} else {result.push(item);}});return result;
}
手写节流函数
函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。
// 函数节流的实现;
function throttle(fn, delay) {let curTime = Date.now();return function() {let context = this,args = arguments,nowTime = Date.now();// 如果两次时间间隔超过了指定时间,则执行函数。if (nowTime - curTime >= delay) {curTime = Date.now();return fn.apply(context, args);}};
}
Array.prototype.map()
Array.prototype.map = function(callback, thisArg) {if (this == undefined) {throw new TypeError('this is null or not defined');}if (typeof callback !== 'function') {throw new TypeError(callback + ' is not a function');}const res = [];// 同理const O = Object(this);const len = O.length >>> 0;for (let i = 0; i < len; i++) {if (i in O) {// 调用回调函数并传入新数组res[i] = callback.call(thisArg, O[i], i, this);}}return res;
}
实现apply方法
apply原理与call很相似,不多赘述
// 模拟 apply
Function.prototype.myapply = function(context, arr) {var context = Object(context) || window;context.fn = this;var result;if (!arr) {result = context.fn();} else {var args = [];for (var i = 0, len = arr.length; i < len; i++) {args.push("arr[" + i + "]");}result = eval("context.fn(" + args + ")");}delete context.fn;return result;
};
深克隆(deepclone)
简单版:
const newObj = JSON.parse(JSON.stringify(oldObj));
局限性:
-
他无法实现对函数 、RegExp等特殊对象的克隆
-
会抛弃对象的constructor,所有的构造函数会指向Object
-
对象有循环引用,会报错
面试版:
/*** deep clone* @param {[type]} parent object 需要进行克隆的对象* @return {[type]} 深克隆后的对象*/
const clone = parent => {// 判断类型const isType = (obj, type) => {if (typeof obj !== "object") return false;const typeString = Object.prototype.toString.call(obj);let flag;switch (type) {case "Array":flag = typeString === "[object Array]";break;case "Date":flag = typeString === "[object Date]";break;case "RegExp":flag = typeString === "[object RegExp]";break;default:flag = false;}return flag;};// 处理正则const getRegExp = re => {var flags = "";if (re.global) flags += "g";if (re.ignoreCase) flags += "i";if (re.multiline) flags += "m";return flags;};// 维护两个储存循环引用的数组const parents = [];const children = [];const _clone = parent => {if (parent === null) return null;if (typeof parent !== "object") return parent;let child, proto;if (isType(parent, "Array")) {// 对数组做特殊处理child = [];} else if (isType(parent, "RegExp")) {// 对正则对象做特殊处理child = new RegExp(parent.source, getRegExp(parent));if (parent.lastIndex) child.lastIndex = parent.lastIndex;} else if (isType(parent, "Date")) {// 对Date对象做特殊处理child = new Date(parent.getTime());} else {// 处理对象原型proto = Object.getPrototypeOf(parent);// 利用Object.create切断原型链child = Object.create(proto);}// 处理循环引用const index = parents.indexOf(parent);if (index != -1) {// 如果父数组存在本对象,说明之前已经被引用过,直接返回此对象return children[index];}parents.push(parent);children.push(child);for (let i in parent) {// 递归child[i] = _clone(parent[i]);}return child;};return _clone(parent);
};
局限性:
- 一些特殊情况没有处理: 例如Buffer对象、Promise、Set、Map
- 另外对于确保没有循环引用的对象,我们可以省去对循环引用的特殊处理,因为这很消耗时间
原理详解实现深克隆
相关文章:
百度前端必会手写面试题整理
请实现一个 add 函数,满足以下功能 add(1); // 1 add(1)(2); // 3 add(1)(2)(3);// 6 add(1)(2, 3); // 6 add(1, 2)(3); // 6 add(1, 2, 3); // 6function add(...args) {// 在内部声明一个函数,利用闭包的特性保存并收集…...
ubuntu 安装支持GPU的Docker详细步骤
安装依赖项 sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common 添加 Docker GPG 密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo apt-key fingerpr…...
usbmon+tcpdump+wireshark USB抓包
文章目录usbmon抓包及配合wireshark解析usbmon抓包及配合wireshark解析 usbmon首先编译为内核模块,然后通过modprobe usbmon加载到linux sys文件系统中 rootroot-PC:~# modprobe usbmon 而后 linux系统下安装 tcpdump rootroot-PC:~# apt-get install tcpdump…...
【LeetCode】剑指 Offer 04. 二维数组中的查找 p44 -- Java Version
题目链接: https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/ 1. 题目介绍(04. 二维数组中的查找) 在一个 n * m 的二维数组中,每一行都按照从左到右 非递减 的顺序排序,每一列都按照从上到下 非递…...
TDengine 3.0.2.5 查询再优化!揭秘索引文件的工作原理
TDengine 3.0 虽然对底层做了大规模的优化重构,但是相对于数据文件的工作逻辑和 2.0 相比是整体保持不变的。本系列文章的主旨在于帮助用户深入理解产品,并且拥有基本的性能调试思路,从而获得更好的产品体验。本期文章会在讲解 TDengine 时序…...
蓝牙耳机哪个品牌性价比高?性价比高的无线蓝牙耳机
现如今耳机已经十分普及,大多数人会随身佩戴蓝牙耳机,相较于传统耳机,无线耳机不仅携带方便,舒适度上也更加出色。不过市面上的无线耳机种类繁多,很多朋友不知道该如何挑选,所以小编特意整理了一期性价比高…...
python的disutils创建分发包
python中的distutils包主要用创建共享包,安装包,在平时安装python模块的时候,使用的命令如下: python setup.py install 其实以上代码就是distuitls包提供的功能,直接使用setup.py来进行安装一个包,在用这种…...
【洛谷】P1195 口袋的天空
明显看出为最小生成树,那么:难点在哪里呢?if(cntn-k)//******{flag1;break;}为什么是cntn-k呢而不是k呢?!!!解释:(如果每个已经连在一起了就不能分开,不管多少…...
JavaScript高级程序设计读书分享之3章——3.5操作符
JavaScript高级程序设计(第4版)读书分享笔记记录 适用于刚入门前端的同志 目录 操作符 一元操作符 递增/递减操作符 一元加和减 布尔操作符 逻辑非 逻辑与 逻辑或 乘性操作符 乘法操作符 除法操作符 取模操作符 加性操作符 加法操作符 减法操作符 关系操作符 相等操…...
moveToCoordinateF3DconcatenateRotations
moveToCoordinate 演示视频: 注意:前提是3~6轴机器人机构且不是PickAndPlace 该方法_3D。Poses.moveToCoordinate 移动由 指定的对象,该对象 对应于支持的机器人配置之一,只要标识的机器人配置支持,其第一个动画指向指定坐标和指定旋转。这无需您定义姿势即可工作。 工…...
多线程面试题开胃菜6(5道)
一、Fork/Join 框架是干什么的?大任务自动分散小任务,并发执行,合并小任务结果。二、线程数过多会造成什么异常?线程过多会造成栈溢出,也有可能会造成堆异常。三、说说线程安全的和不安全的集合。Java 中平时用的最多的…...
植物大战 List——C++
这里写目录标题vector和stirng的细节对于stringlist的使用list的迭代器反向迭代器构造函数关于list::sort的排序uniquelist的底层模拟实现结点类的实现迭代器模拟实现list实现插入的实现迭代器失效inserterase析构函数拷贝构造赋值构造函数vector和stirng的细节 复习vector的深…...
安灯(andon)系统是车间现场管理的必备工具
安灯(andon)系统应用越来越广泛,不单单局限于汽车行业,更多生产型企业意识到了提高工作效率的重要性,提高工作效率根本的能提高生产水平,提高产量,而且安灯(andon)系统不…...
Hazel游戏引擎(004)
本人菜鸟,文中若有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/GameEngineLightWeight(中文的注释适合中国人的你) 文章目录前言操作步骤讲解GitHubHazel项目此项目定位项目属性修改Sand…...
【CS224W】(task4)图嵌入表示学习
note node2vec: 计算随机游走概率从节点uuu开始模拟rrr条长度为lll的游走链路使用 Stochastic Gradient Descent 优化损失函数 Node2vec在节点分类方面表现更好;而其他方法在链路预测上效果更好,如random walk效率更高;graph emb…...
分享111个HTML医疗保健模板,总有一款适合您
分享111个HTML医疗保健模板,总有一款适合您 111个HTML医疗保健模板下载链接:https://pan.baidu.com/s/1YInaQDnUVsXYtMh1Ls-BHg?pwdxvfc 提取码:xvfc Python采集代码下载链接:采集代码.zip - 蓝奏云 import os import shuti…...
山东大学2022操作系统期末
接力:山东大学2021操作系统期末 2022—2023山东大学计算机操作系统期末考试回忆版 简答题(4 10 points) (1)用户态,核心态是什么 (2)这种区分对现代操作系统的意义 (3)printf(“…...
Hadoop高可用搭建(一)
目录 创建多台虚拟机 修改计算机名称 快速生效 修改网络信息 重启网络服务 关闭和禁用每台机的防火墙 同步时间 安装ntpdate 定时更新时间 启动定时任务 设置集群中每台机器的/etc/hosts 把hosts拷贝发送到每一台虚拟机 配置免密登陆 将本机的公钥拷贝到要免密登…...
算法 - 剑指Offer 重建二叉树
题目 输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 解题思路 这题较为复杂, 首先审题,前序遍历规则:根左右, 中序遍历&#x…...
手写JavaScript常见5种设计模式
想分享的几种设计模式 目前模式:工厂模式,单例模式,适配器模式,装饰者模式,建造者模式 建造者模式 简介:建造者模式(builder pattern)比较简单,它属于创建型模式的一种…...
Python 异步: 当前和正在运行的任务(9)
我们可以反省在 asyncio 事件循环中运行的任务。这可以通过为当前运行的任务和所有正在运行的任务获取一个 asyncio.Task 对象来实现。 1. 如何获取当前任务 我们可以通过 asyncio.current_task() 函数获取当前任务。此函数将为当前正在运行的任务返回一个任务对象。 ... # …...
REDIS-雪崩、击穿、穿透
直接发车🚗 一.雪崩 1.触发原因 A.大量缓存数据在同一时间过期(失效) B.redis故障宕机 上述均导致全部请求去访问数据库,导致DB压力骤增,严重则导致数据库宕机/系统宕机 2.应对策略 不同触发原因,应对策略也不一致 应对A&a…...
什么人合适学习Python
发了几天的Python基础,也认识了一些朋友,忽然有人问起,说为啥学Python,或者说啥人学习Python,作为一个教龄8年从Python一线讲师到Python教学主管的我和大家分享一下个人的看法,还是提前说一下,个…...
greenDao的使用文档
介绍:greenDAO 是一款轻量级的 Android ORM 框架,将 Java 对象映射到 SQLite 数据库中,我们操作数据库的时候,不在需要编写复杂的 SQL语句, 在性能方面,greenDAO 针对 Android 进行了高度优化, …...
基于JAVA+SpringBoot+LayUI+Shiro的仓库管理系统
基于JAVASpringBootLayUIShiro的仓库管理系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项…...
金三银四面试必看,复盘字节测试开发面试:一次测试负责人岗位面试总结
最近面试了某企业的测试负责人岗位,历经四面,收获蛮多的。 这篇文章,我想聊聊这次面试过程中的一些经历,以及些许经验和教训。 岗位要求 岗位名称:测试负责人 岗位要求:1、扎实的技术以及丰富的技术项目…...
【算法自由之路】 贪心算法
贪心算法 局部最右得到全局最右难点在于如何证明局部最优可以得到全局最优堆 和 排序 是贪心算法最常用的实现算法 贪心算法作为最符合自然智慧的算法,思路是从小部分取最优从而获得最终的最优,但是难得是怎样获取部分最优才能得到全局最优。 有时候我…...
Scratch少儿编程案例-水果忍者-学生作业
专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...
7.Docker Compose
Docker Compose 介绍 Docker Compose是Docker官方编排(Orchestration)项目之一,负责快速的部署分布式应用。其代码目前在https://github.com/docker/compose上开源。Compose 定位是 「定义和运行多个 Docker 容器的应用(Definin…...
GitHub访问问题与 Steam++下载及使用(适合小白)
前言 📜 “ 作者 久绊A ” 专注记录自己所整理的Java、web、sql等,IT技术干货、学习经验、面试资料、刷题记录,以及遇到的问题和解决方案,记录自己成长的点滴 目录 前言 一、Steam的介绍 1、大概介绍 2、详细介绍 二、Ste…...
做网站宣传图片/网盘资源
网站请勿随意使用第三方CDN资源调用公开库资源 - 聆听分享网...
电子商务网站建设前期/百度指数是免费的吗
文章预览前言RxJava的简单使用1、环境准备2、activity_main.xml3、MianActivity.java4、效果预览RxJava操作符1、创建操作符2、转换操作符3、 合并操作符4、功能操作符5、过滤操作符前言 官方的定义:一个在Java VM上使用可观测的序列,组成异步的、基于事…...
jsp做网站用什么封装字符串/长沙网络营销学校
本文转自Roboters blog 对D-Bus Tutorial 进行了一些翻译加上自己的一些理解。 有很多种IPC或者网络通信系统,如:CORBA, DCE, DCOM, DCOP, XML-RPC, SOAP, MBUS, Internet Communications Engine (ICE)等等,可能会有数百种,dbus…...
wordpress 的客户端/百度在线咨询
公众号 全网唯一一个从0开始帮助Java开发者转做大数据领域的公众号~ 大数据技术与架构或者搜索import_bigdata关注~ 海量【java和大数据的面试题+视频资料】整理在公众号,关注后可以下载~ JVM内存回收机制简述 JVM内存回收机制涉及的知识点太多了,了解越多越迷糊,汗一个,这…...
泰安企业建站公司服务/郑州seo优化顾问
一直对抖音上的各种人脸处理算法很感兴趣,个别的我觉得目前的水平我能写个简单的实现方式,但是涉及复杂的,还是太菜了。但是之前在抖音上看到了一个用网页写的旋转汉字时钟的视频,感觉很好玩,而且我觉着写出来完全没问…...
centos架设wordpress/徐州网络推广服务
A答案如下所示:在Oracle中,DBID和DBNAME是两个极其重要的对象。作为标记信息,DBID和DBNAME包含在参数文件、密码文件、数据文件、日志文件、备份集合、归档日志中。一般情况下,已经创建好的数据库是不需要修改DBID和DBNAME的。因为…...