还在害怕手写题吗,本文可以帮你扩展并巩固自己的JS基础,顺便搞定90%的手写题。在工作中还可以对常用的需求进行手写实现,比如深拷贝、防抖节流等可以直接用于往后的项目中,提高项目开发效率。不说废话了,下面就直接上代码吧。

1.call的实现

  • 第一个参数为null或者undefined时,this指向全局对象window,值为原始值的指向该原始值的自动包装对象,如 String、Number、Boolean

  • 为了避免函数名与上下文(context)的属性发生冲突,使用Symbol类型作为唯一值

  • 将函数作为传入的上下文(context)属性执行

  • 函数执行完成后删除该属性

  • 返回执行结果

Function.prototype.myCall = function(context,...args){let cxt = context || window;//将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)//新建一个唯一的Symbol变量避免重复let func = Symbol() cxt[func] = this;args = args ? args : []//以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向const res = args.length > 0 ? cxt[func](...args) : cxt[func]();//删除该方法,不然会对传入对象造成污染(添加该方法)delete cxt[func];return res;
}

2.apply的实现

  • 前部分与call一样

  • 第二个参数可以不传,但类型必须为数组或者类数组

Function.prototype.myApply = function(context,args = []){let cxt = context || window;//将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)//新建一个唯一的Symbol变量避免重复let func = Symbol()cxt[func] = this;//以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向const res = args.length > 0 ? cxt[func](...args) : cxt[func]();delete cxt[func];return res;
}

3.bind的实现

需要考虑:

  • bind() 除了 this 外,还可传入多个参数;

  • bind 创建的新函数可能传入多个参数;

  • 新函数可能被当做构造函数调用;

  • 函数可能有返回值;

实现方法:

  • bind 方法不会立即执行,需要返回一个待执行的函数;(闭包)

  • 实现作用域绑定(apply)

  • 参数传递(apply 的数组传参)

  • 当作为构造函数的时候,进行原型继承

Function.prototype.myBind = function (context, ...args) {//新建一个变量赋值为this,表示当前函数const fn = this//判断有没有传参进来,若为空则赋值[]args = args ? args : []//返回一个newFn函数,在里面调用fnreturn function newFn(...newFnArgs) {if (this instanceof newFn) {return new fn(...args, ...newFnArgs)}return fn.apply(context, [...args,...newFnArgs])}
}
  • 测试

let name = '小王',age =17;
let obj = {name:'小张',age: this.age,myFun: function(from,to){console.log(this.name + ' 年龄 ' + this.age+'来自 '+from+'去往'+ to)}
}
let db = {name: '德玛',age: 99
}//结果
obj.myFun.myCall(db,'成都','上海');     // 德玛 年龄 99  来自 成都去往上海
obj.myFun.myApply(db,['成都','上海']);      // 德玛 年龄 99  来自 成都去往上海
obj.myFun.myBind(db,'成都','上海')();       // 德玛 年龄 99  来自 成都去往上海
obj.myFun.myBind(db,['成都','上海'])();   // 德玛 年龄 99  来自 成都, 上海去往 undefined

4.寄生式组合继承

function Person(obj) {this.name = obj.namethis.age = obj.age
}
Person.prototype.add = function(value){console.log(value)
}
var p1 = new Person({name:"番茄", age: 18})function Person1(obj) {Person.call(this, obj)this.sex = obj.sex
}
// 这一步是继承的关键
Person1.prototype = Object.create(Person.prototype);
Person1.prototype.constructor = Person1;Person1.prototype.play = function(value){console.log(value)
}
var p2 = new Person1({name:"鸡蛋", age: 118, sex: "男"})

5.ES6继承

//class 相当于es5中构造函数
//class中定义方法时,前后不能加function,全部定义在class的protopyte属性中
//class中定义的所有方法是不可枚举的
//class中只能定义方法,不能定义对象,变量等
//class和方法内默认都是严格模式
//es5中constructor为隐式属性
class People{constructor(name='wang',age='27'){this.name = name;this.age = age;}eat(){console.log(`${this.name} ${this.age} eat food`)}
}
//继承父类
class Woman extends People{ constructor(name = 'ren',age = '27'){ //继承父类属性super(name, age); } eat(){ //继承父类方法super.eat() }
}
let wonmanObj=new Woman('xiaoxiami');
wonmanObj.eat();//es5继承先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.apply(this))。
//es6继承是使用关键字super先创建父类的实例对象this,最后在子类class中修改this。

6.new的实现

  • 一个继承自 Foo.prototype 的新对象被创建。

  • 使用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。

  • 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。

  • 一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤

function Ctor(){....
}function myNew(ctor,...args){if(typeof ctor !== 'function'){throw 'myNew function the first param must be a function';}var newObj = Object.create(ctor.prototype); //创建一个继承自ctor.prototype的新对象var ctorReturnResult = ctor.apply(newObj, args); //将构造函数ctor的this绑定到newObj中var isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null;var isFunction = typeof ctorReturnResult === 'function';if(isObject || isFunction){return ctorReturnResult;}return newObj;
}let c = myNew(Ctor);

7.instanceof的实现

  • instanceof 是用来判断A是否为B的实例,表达式为:A instanceof B,如果A是B的实例,则返回true,否则返回false。

  • instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。

  • 不能检测基本数据类型,在原型链上的结果未必准确,不能检测null,undefined

  • 实现:遍历左边变量的原型链,直到找到右边变量的 prototype,如果没有找到,返回 false

function myInstanceOf(a,b){let left = a.__proto__;let right = b.prototype;while(true){if(left == null){return false}if(left == right){return true}left = left.__proto__}
}//instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
function myInstanceof(left, right) {let proto = Object.getPrototypeOf(left), // 获取对象的原型prototype = right.prototype; // 获取构造函数的 prototype 对象// 判断构造函数的 prototype 对象是否在对象的原型链上while (true) {if (!proto) return false;if (proto === prototype) return true;proto = Object.getPrototypeOf(proto);}
}

8.Object.create()的实现

  • MDN文档

  • Object.create()会将参数对象作为一个新创建的空对象的原型, 并返回这个空对象

//简略版
function myCreate(obj){// 新声明一个函数function C(){};// 将函数的原型指向objC.prototype = obj;// 返回这个函数的实力化对象return new C()
}
//官方版Polyfill
if (typeof Object.create !== "function") {Object.create = function (proto, propertiesObject) {if (typeof proto !== 'object' && typeof proto !== 'function') {throw new TypeError('Object prototype may only be an Object: ' + proto);} else if (proto === null) {throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");}if (typeof propertiesObject !== 'undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");function F() {}F.prototype = proto;return new F();};
}

9.实现 Object.assign

Object.assign2 = function(target, ...source) {if (target == null) {throw new TypeError('Cannot convert undefined or null to object')}let ret = Object(target) source.forEach(function(obj) {if (obj != null) {for (let key in obj) {if (obj.hasOwnProperty(key)) {ret[key] = obj[key]}}}})return ret
}

10.Promise的实现

实现 Promise 需要完全读懂 Promise A+ 规范,不过从总体的实现上看,有如下几个点需要考虑到:

  • Promise本质是一个状态机,且状态只能为以下三种:Pending(等待态)、Fulfilled(执行态)、Rejected(拒绝态),状态的变更是单向的,只能从Pending -> Fulfilled 或 Pending -> Rejected,状态变更不可逆

  • then 需要支持链式调用

class Promise {callbacks = [];state = 'pending';//增加状态value = null;//保存结果constructor(fn) {fn(this._resolve.bind(this), this._reject.bind(this));}then(onFulfilled, onRejected) {return new Promise((resolve, reject) => {this._handle({onFulfilled: onFulfilled || null,onRejected: onRejected || null,resolve: resolve,reject: reject});});}_handle(callback) {if (this.state === 'pending') {this.callbacks.push(callback);return;}let cb = this.state === 'fulfilled' ? callback.onFulfilled : callback.onRejected;if (!cb) {//如果then中没有传递任何东西cb = this.state === 'fulfilled' ? callback.resolve : callback.reject;cb(this.value);return;}let ret = cb(this.value);cb = this.state === 'fulfilled' ? callback.resolve : callback.reject;cb(ret);}_resolve(value) {if (value && (typeof value === 'object' || typeof value === 'function')) {var then = value.then;if (typeof then === 'function') {then.call(value, this._resolve.bind(this), this._reject.bind(this));return;}}this.state = 'fulfilled';//改变状态this.value = value;//保存结果this.callbacks.forEach(callback => this._handle(callback));}_reject(error) {this.state = 'rejected';this.value = error;this.callbacks.forEach(callback => this._handle(callback));}
}

Promise.resolve

  • Promsie.resolve(value) 可以将任何值转成值为 value 状态是 fulfilled 的 Promise,但如果传入的值本身是 Promise 则会原样返回它。

Promise.resolve(value) {if (value && value instanceof Promise) {return value;} else if (value && typeof value === 'object' && typeof value.then === 'function') {let then = value.then;return new Promise(resolve => {then(resolve);});} else if (value) {return new Promise(resolve => resolve(value));} else {return new Promise(resolve => resolve());}
}

Promise.reject

  • 和 Promise.resolve() 类似,Promise.reject() 会实例化一个 rejected 状态的 Promise。但与 Promise.resolve() 不同的是,如果给 Promise.reject() 传递一个 Promise 对象,则这个对象会成为新 Promise 的值。

Promise.reject = function(reason) {return new Promise((resolve, reject) => reject(reason))
}

Promise.all

  • 传入的所有 Promsie 都是 fulfilled,则返回由他们的值组成的,状态为 fulfilled 的新 Promise;

  • 只要有一个 Promise 是 rejected,则返回 rejected 状态的新 Promsie,且它的值是第一个 rejected 的 Promise 的值;

  • 只要有一个 Promise 是 pending,则返回一个 pending 状态的新 Promise;

Promise.all = function(promiseArr) {let index = 0, result = []return new Promise((resolve, reject) => {promiseArr.forEach((p, i) => {Promise.resolve(p).then(val => {index++result[i] = valif (index === promiseArr.length) {resolve(result)}}, err => {reject(err)})})})
}

Promise.race

  • Promise.race 会返回一个由所有可迭代实例中第一个 fulfilled 或 rejected 的实例包装后的新实例。

Promise.race = function(promiseArr) {return new Promise((resolve, reject) => {promiseArr.forEach(p => {Promise.resolve(p).then(val => {resolve(val)}, err => {rejecte(err)})})})
}

11.Ajax的实现

function ajax(url,method,body,headers){return new Promise((resolve,reject)=>{let req = new XMLHttpRequest();req.open(methods,url);for(let key in headers){req.setRequestHeader(key,headers[key])}req.onreadystatechange(()=>{if(req.readystate == 4){if(req.status >= '200' && req.status <= 300){resolve(req.responeText)}else{reject(req)}}})req.send(body)})
}

12.实现防抖函数(debounce)

  • 连续触发在最后一次执行方法,场景:输入框匹配

let debounce = (fn,time = 1000) => {let timeLock = nullreturn function (...args){clearTimeout(timeLock)timeLock = setTimeout(()=>{fn(...args)},time)}
}

13.实现节流函数(throttle)

  • 在一定时间内只触发一次,场景:长列表滚动节流

let throttle = (fn,time = 1000) => {let flag = true;return function (...args){if(flag){flag = false;setTimeout(()=>{flag = true;fn(...args)},time)}}
}

14.深拷贝(deepclone)

  • 判断类型,正则和日期直接返回新对象

  • 空或者非对象类型,直接返回原值

  • 考虑循环引用,判断如果hash中含有直接返回hash中的值

  • 新建一个相应的new obj.constructor加入hash

  • 遍历对象递归(普通key和key是symbol情况)

function deepClone(obj,hash = new WeakMap()){if(obj instanceof RegExp) return new RegExp(obj);if(obj instanceof Date) return new Date(obj);if(obj === null || typeof obj !== 'object') return obj;//循环引用的情况if(hash.has(obj)){return hash.get(obj)}//new 一个相应的对象//obj为Array,相当于new Array()//obj为Object,相当于new Object()let constr = new obj.constructor();hash.set(obj,constr);for(let key in obj){if(obj.hasOwnProperty(key)){constr[key] = deepClone(obj[key],hash)}}//考虑symbol的情况let symbolObj = Object.getOwnPropertySymbols(obj)for(let i=0;i<symbolObj.length;i++){if(obj.hasOwnProperty(symbolObj[i])){constr[symbolObj[i]] = deepClone(obj[symbolObj[i]],hash)}}return constr
}

15.数组扁平化的实现(flat)

let arr = [1,2,[3,4,[5,[6]]]]
console.log(arr.flat(Infinity))//flat参数为指定要提取嵌套数组的结构深度,默认值为 1
//用reduce实现
function fn(arr){return arr.reduce((prev,cur)=>{return prev.concat(Array.isArray(cur)?fn(cur):cur)},[])
}

16.函数柯里化

function sumFn(a,b,c){return a+ b + c};
let sum = curry(sumFn);
sum(2)(3)(5)//10
sum(2,3)(5)//10
function curry(fn,...args){let fnLen = fn.length,argsLen = args.length;//对比函数的参数和当前传入参数//若参数不够就继续递归返回curry//若参数够就调用函数返回相应的值if(fnLen > argsLen){return function(...arg2s){return curry(fn,...args,...arg2s)}}else{return fn(...args)}
}

17.使用闭包实现每隔一秒打印 1,2,3,4

for (var i=1; i<=5; i++) {(function (i) {setTimeout(() => console.log(i), 1000*i)})(i)
}

18.手写一个 jsonp

const jsonp = function (url, data) {return new Promise((resolve, reject) => {// 初始化urllet dataString = url.indexOf('?') === -1 ? '?' : ''let callbackName = `jsonpCB_${Date.now()}`url += `${dataString}callback=${callbackName}`if (data) {// 有请求参数,依次添加到urlfor (let k in data) {url += `${k}=${data[k]}`}}let jsNode = document.createElement('script')jsNode.src = url// 触发callback,触发后删除js标签和绑定在window上的callbackwindow[callbackName] = result => {delete window[callbackName]document.body.removeChild(jsNode)if (result) {resolve(result)} else {reject('没有返回数据')}}// js加载异常的情况jsNode.addEventListener('error', () => {delete window[callbackName]document.body.removeChild(jsNode)reject('JavaScript资源加载失败')}, false)// 添加js节点到document上时,开始请求document.body.appendChild(jsNode)})
}
jsonp('http://192.168.0.103:8081/jsonp', {a: 1,b: 'heiheihei'
})
.then(result => {console.log(result)
})
.catch(err => {console.error(err)
})

19.手写一个观察者模式

class Subject{constructor(name){this.name = namethis.observers = []this.state = 'XXXX'}// 被观察者要提供一个接受观察者的方法attach(observer){this.observers.push(observer)}// 改变被观察着的状态setState(newState){this.state = newStatethis.observers.forEach(o=>{o.update(newState)})}
}class Observer{constructor(name){this.name = name}update(newState){console.log(`${this.name}say:${newState}`)}
}// 被观察者 灯
let sub = new Subject('灯')
let mm = new Observer('小明')
let jj = new Observer('小健')// 订阅 观察者
sub.attach(mm)
sub.attach(jj)sub.setState('灯亮了来电了')

20.EventEmitter 实现

class EventEmitter {constructor() {this.events = {};}on(event, callback) {let callbacks = this.events[event] || [];callbacks.push(callback);this.events[event] = callbacks;return this;}off(event, callback) {let callbacks = this.events[event];this.events[event] = callbacks && callbacks.filter(fn => fn !== callback);return this;}emit(event, ...args) {let callbacks = this.events[event];callbacks.forEach(fn => {fn(...args);});return this;}once(event, callback) {let wrapFun = function (...args) {callback(...args);this.off(event, wrapFun);};this.on(event, wrapFun);return this;}
}

21.生成随机数的各种方法?

function getRandom(min, max) {return Math.floor(Math.random() * (max - min)) + min
}

22.如何实现数组的随机排序?

let arr = [2,3,454,34,324,32]
arr.sort(randomSort)
function randomSort(a, b) {return Math.random() > 0.5 ? -1 : 1;
}

23.写一个通用的事件侦听器函数。

const EventUtils = {// 视能力分别使用dom0||dom2||IE方式 来绑定事件// 添加事件addEvent: function(element, type, handler) {if (element.addEventListener) {element.addEventListener(type, handler, false);} else if (element.attachEvent) {element.attachEvent("on" + type, handler);} else {element["on" + type] = handler;}},// 移除事件removeEvent: function(element, type, handler) {if (element.removeEventListener) {element.removeEventListener(type, handler, false);} else if (element.detachEvent) {element.detachEvent("on" + type, handler);} else {element["on" + type] = null;}},// 获取事件目标getTarget: function(event) {return event.target || event.srcElement;},// 获取 event 对象的引用,取到事件的所有信息,确保随时能使用 eventgetEvent: function(event) {return event || window.event;},// 阻止事件(主要是事件冒泡,因为 IE 不支持事件捕获)stopPropagation: function(event) {if (event.stopPropagation) {event.stopPropagation();} else {event.cancelBubble = true;}},// 取消事件的默认行为preventDefault: function(event) {if (event.preventDefault) {event.preventDefault();} else {event.returnValue = false;}}
};

24.使用迭代的方式实现 flatten 函数。

var arr = [1, 2, 3, [4, 5], [6, [7, [8]]]]
/** * 使用递归的方式处理 * wrap 内保
存结果 ret * 返回一个递归函数 **/
function wrap() {var ret = [];return function flat(a) {for (var item ofa) {if (item.constructor === Array) {ret.concat(flat(item))} else {ret.push(item)}}return ret}
}
console.log(wrap()(arr));

25.怎么实现一个sleep

  • sleep函数作用是让线程休眠,等到指定时间在重新唤起。

function sleep(delay) {var start = (new Date()).getTime();while ((new Date()).getTime() - start < delay) {continue;}
}function test() {console.log('111');sleep(2000);console.log('222');
}test()

26.实现正则切分千分位(10000 => 10,000)

//无小数点
let num1 = '1321434322222'
num1.replace(/(\d)(?=(\d{3})+$)/g,'$1,')
//有小数点
let num2 = '342243242322.3432423'
num2.replace(/(\d)(?=(\d{3})+\.)/g,'$1,')

27.对象数组去重

输入:
[{a:1,b:2,c:3},{b:2,c:3,a:1},{d:2,c:2}]
输出:
[{a:1,b:2,c:3},{d:2,c:2}]
  • 首先写一个函数把对象中的key排序,然后再转成字符串

  • 遍历数组利用Set将转为字符串后的对象去重

function objSort(obj){let newObj = {}//遍历对象,并将key进行排序Object.keys(obj).sort().map(key => {newObj[key] = obj[key]})//将排序好的数组转成字符串return JSON.stringify(newObj)
}function unique(arr){let set = new Set();for(let i=0;i<arr.length;i++){let str = objSort(arr[i])set.add(str)}//将数组中的字符串转回对象arr = [...set].map(item => {return JSON.parse(item)})return arr
}

28.解析 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;
}

29.模板引擎实现

let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let data = {name: '姓名',age: 18
}
render(template, data); // 我是姓名,年龄18,性别undefined
function render(template, data) {const reg = /\{\{(\w+)\}\}/; // 模板字符串正则if (reg.test(template)) { // 判断模板里是否有模板字符串const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段template = template.replace(reg, data[name]); // 将第一个模板字符串渲染return render(template, data); // 递归的渲染并返回渲染后的结构}return template; // 如果模板没有模板字符串直接返回
}

30.转化为驼峰命名

var s1 = "get-element-by-id"
// 转化为 getElementById
var f = function(s) {return s.replace(/-\w/g, function(x) {return x.slice(1).toUpperCase();})
}

31.查找字符串中出现最多的字符和个数

  • 例: abbcccddddd -> 字符最多的是d,出现了5次

let str = "abcabcabcbbccccc";
let num = 0;
let char = '';// 使其按照一定的次序排列
str = str.split('').sort().join('');
// "aaabbbbbcccccccc"// 定义正则表达式
let re = /(\w)\1+/g;
str.replace(re,($0,$1) => {if(num < $0.length){num = $0.length;char = $1;        }
});
console.log(`字符最多的是${char},出现了${num}次`);

32.图片懒加载

let imgList = [...document.querySelectorAll('img')]
let length = imgList.lengthconst imgLazyLoad = function() {let count = 0return (function() {let deleteIndexList = []imgList.forEach((img, index) => {let rect = img.getBoundingClientRect()if (rect.top < window.innerHeight) {img.src = img.dataset.srcdeleteIndexList.push(index)count++if (count === length) {document.removeEventListener('scroll', imgLazyLoad)}}})imgList = imgList.filter((img, index) => !deleteIndexList.includes(index))})()
}// 这里最好加上防抖处理
document.addEventListener('scroll', imgLazyLoad)

参考资料

  • 高频 JavaScript 手写

  • 初、中级前端应该要掌握的手写代码实现

  • 22 道高频 JavaScript 手写

  • 死磕 36 个 JS 手写题(搞懂后,提升真的大)

作者:xpsilvester

原文链接:https://juejin.cn/post/6963167124881670152

推荐阅读

前端面试js高频手写大全

END

关注下方「前端开发博客」,回复 “电子书”

领取27本电子书

❤️ 看完两件事

如果你觉得这篇内容对你挺有启发,我想邀请你帮我两个小忙:

  1. 点个「在看」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)

  2. 关注公众号「前端开发博客」,每周重点攻克一个前端面试重难点,

  3. 公众号后台回复「电子书」即可免费获取 27本 精选的前端电子书!

点个在看支持我吧,转发就更好了

一文帮你搞定90%的JS手写题相关推荐

  1. 【面试】970- 一文帮你搞定90%的JS手写题

    还在害怕手写题吗,本文可以帮你扩展并巩固自己的JS基础,顺便搞定90%的手写题.在工作中还可以对常用的需求进行手写实现,比如深拷贝.防抖节流等可以直接用于往后的项目中,提高项目开发效率.不说废话了,下 ...

  2. 【干货知识】Redis:从应用到底层,一文帮你搞定

    1.基本类型及底层实现 1.1.String 用途: 适用于简单key-value存储.setnx key value实现分布式锁.计数器(原子性).分布式全局唯一ID. 底层:C语言中String用 ...

  3. Redis:从应用到底层,一文帮你搞定

    1.基本类型及底层实现 1.1.String 用途: 适用于简单key-value存储.setnx key value实现分布式锁.计数器(原子性).分布式全局唯一ID. 底层:C语言中String用 ...

  4. python 二叉树中所有距离为k的节点_Redis:从应用到底层,一文帮你搞定

    高清思维导图已同步Git:https://github.com/SoWhat1412/xmindfile,关注公众号sowhat1412获取海量资源 总感觉哪里不对,但是又说不上来 1.基本类型及底层 ...

  5. python dfs算法_LeetCode | 一文帮你搞定BFS、DFS算法(python版)

    模板方法 使用BFS,DFS的题目,在leetcode上一般标记为medium或者hard.但从思维逻辑上看,其难度定义偏高.可能从代码量来看,写一道BFS或者DFS的篇幅比其他类型的题目要多. BF ...

  6. c++ 怎样连接两个链表_LeetCode | 链表的入口,一文帮你搞定“环形链表”(python版,最简单解析)...

    链表节点的定义 链表作为一种数据结构,由链表节点互相连接构成. 链表节点包含自身的数据和一个指向下一节点的指针. """ Definition of ListNode & ...

  7. java this关键字的使用_做java两年了,构造方法和方法重载还是搞不明白?一文帮你搞定...

    成员方法 类成员主要包括成员变量和成员方法. 带参数的成员方法 带参数的成员方法可以接受用户输入的内容.创建带参数的方法时定义的参数叫形式参数,即形参:调用方法时传入的参数叫实际参数,即实参. 语法结 ...

  8. 物理学习:6招帮你搞定高中物理考试的计算题

    物理部分一般是3道理论大题,其中两道力学题一道电学题,也有一道力学题两道电学题的情况,不过这种情况较少.其中,力学题常常以物体的碰撞或连接体为背景,涉及匀变速直线运动规律.牛顿运动定律.平抛运动与圆周 ...

  9. 如何删除Word页眉下横线?只需1招即可轻松帮你搞定!

    在我们职场办公时候经常会处理各种Word文档,这时候总会遇到各种类型的问题,就比如页眉下讨人厌的横线,经常为这个莫名其妙的横线而感到头疼,关键它还删除不掉! 针对这个问题,特意为大家整理了几个小技巧, ...

最新文章

  1. 山东计算机类好的民办大学,山东四大坑人学校-山东坑人的民办大学(野鸡大学)...
  2. SDN/NFV 网络技术系列文章
  3. python语言中文社区-python numpy看这一篇就够了-Go语言中文社区
  4. 11个有用的移动网页开发App和HTML5框架
  5. getlab如何编辑提交时显示的用户名_GitHub 如何让你的提交显示被校验
  6. SAP Spartacus Definition of Done
  7. SAP License:BW/BCS(BO)难在那里--SAP中的公司和会计凭证
  8. 由于找不到appvisvsubsystems32.dll_老实人就别找女朋友了 跟个老实人结婚有多累_新闻资讯...
  9. EMC标准与测试方法
  10. 手把手教你关闭iphone系统自动下载(新增IOS11描述性文件地址)
  11. C2872 “detail”: 不明确的符号
  12. BaseFx实习小记(三)
  13. BeanUtils的populate方法之日期处理
  14. 浅谈UAC ByPass
  15. 京东平台的产品标题的优化有什么技巧?
  16. 分布式系统论文精读2:GFS
  17. 巴菲特抄底台积电,透露出哪些信号?
  18. Ubuntu make 降级方法
  19. 2022抖音私信名片系统源码+链接跳转引流技术
  20. python中的pop()函数

热门文章

  1. 【2019年06月28日】A股最便宜的股票
  2. 《羊了个羊》一夜爆红?产品运营带来的巨大红利
  3. selenium实例
  4. java三板斧_JAVA基础学习 三板斧
  5. 分布式存储的架构以及存在的问题和解决办法1
  6. Redis | 26.Redis事务案例 - 秒杀 - 库存遗留问题
  7. 富士通ERP解决方案举例
  8. 在WinXP镜像中手工集成sata驱动。
  9. tesseract-ocr引擎学习笔记
  10. Oracle查询速度慢的原因总结