1.js 处理并发请求
要请求100次,只能有n个请求同时进行,怎么处理
简单代码实现
function myRequest(totalArr, n){
let count = 0;
let len = totalArr.length;
let successNumber = 0;
(function httpRequest(){
if(count < n && totalArr.length>0){
imgArr.shift();
count++;
setTimeout(res => {
count --;
successNumber ++
httpRequest()
if(successNumber === len){
console.log('结束')
}
},100)
}
})()
}
myRequest([1,2,4,5,6], 2)
思路
- 用一个
count
记录当前正在请求的数量。 - 用一个递归函数(下一步用到),里面循环调用请求,每发送一次请求,
count
加1,当count达到给定限定值时停止调用 - 在调用返回的时候
count
减少一,回调递归函数
2.实现一个函数加载js
代码实现
function loadJS(url) {
return new Promise(resolve => {
let script = document.createElement('script')
script.src = url
script.onload = function () {
console.log('success')
resolve('get')
}
document.querySelector('head').appendChild(script)
})
}
loadJS('./index.js').then(res => {
console.log(res)
})
3. jsonp 实现
代码实现
function callbackFunction(result, methodName) {
var html = '<ul>';
for(var i = 0; i < result.length; i++)
{
html += '<li>' + result[i] + '</li>';
}
html += '</ul>';
document.getElementById('divCustomers').innerHTML = html;
}
function jsonp(url, params, callback) {
let script = document.createElement('script')
script.src = url + '?jsoncallback='+callback.name
document.querySelector('head').appendChild(script)
}
jsonp('https://www.runoob.com/try/ajax/jsonp.php', '', callbackFunction)
4. js实现深拷贝
function deepCopy(target) {
// 深拷贝不一定拷贝的都是对象,可以拷贝任何东西
// 只有数组和对象需要递归获取,其它直接返回
const type = Object.prototype.toString.call(target)
if(type !== '[object Object]' || type !== '[object Array]' || type === '[object Null]'){
return target
}
// 经过上面的判断,这里的就都是对象了(对象和数组)
let newObj
if(Object.prototype.toString.call(target) === '[object Object]'){
newObj = Object.create(null)
} else {
newObj = []
}
Object.keys(target).forEach(key => {
if(target.hasOwnProperty(key)){
newObj[key] = deepCopy(target[key])
}
})
return newObj
}
5. 比较两个值是否相等
可以比较任何值,可以使基本数据类型和引用数据类型,代码如下
function ifEqual(target1, target2) {
let t1Type = Object.prototype.toString.call(target1)
let t2Type = Object.prototype.toString.call(target2)
if (t1Type !== t2Type) {
return false
}
if (t1Type === '[object Null]') {
return true
}
if (t1Type === '[object Undefined]') {
return false
}
if (t1Type === '[object Object]' || t1Type === '[object Array]') {
let keys1 = Object.keys(target1)
let keys2 = Object.keys(target2)
if (keys1.length !== keys2.length) {
// 如果相比对象的keys长度不同,不相等
return false
}
let result
for(let i=0;i<keys1.length;i++){
if (!ifEqual(target1[keys1[i]], target2[keys1[i]])){
result = false
}
}
return result
} else {
return target1 === target2
}
}
6. 函数柯里化2
function rawMethod(a) {
return a + 1;
}
function middleware1(next) {
return function(a) {
return next(a) + 1;
};
}
function middleware2(next) {
return function(a) {
return next(a) + 1;
};
}
function middleware3(next) {
return function(a) {
return next(a) + 1;
};
}
// 请实现该方法
const applyMiddleWare = (originalMethod, ...args) => {
// 请实现该方法
const applyMiddleWare = (originalMethod, ...args) => {
// 根据题目,需要如下处理函数:middleware3(middleware2(middleware1(rawMethod)))(n)
// 这个函数层层嵌套,那么可以使用数组的reduce方法
// 查看执行顺序,和reduce的顺序,这里除了第一个函数外,需要取相反方向,不能用sort,会改变原数组
/*
let funs = [].concat(originalMethod,args);
let initFn = funs[0]
let otherFn = []
for(let i=funs.length-1;i>0;i--){
otherFn.push(funs[i])
}
return otherFn.reduce((result, current) => {
return current(result)
},initFn)
*/
// 上过面的方法只要执行 applyMiddleWare 就已经执行了他的参数方法
// 所以 applyMiddleWare(newMethod, middleware1) 这里的23先于1执行
// 那么就考虑将参数方法在包一层,在函数调用里执行
let funs = [].concat(originalMethod,args)
const len = funs.length
if(len === 0){
return arg => arg;
}else if(len === 1){
return funs[0]
}else{
return funs.reduce((a, b) => {
return (n)=> {
return b(a)(n)
}
})
}
}
}
// 上面函数实际上返回如下
let z1 = n => middleware1(n => middleware2(n => middleware3(rawMethod)(n))(n))(n)
// 1. n => 里面函数结果 + 1
// 2. 里面函数结构 = 里面函数结构 + 1
// 3. 里面函数结构 = 里面函数结构 + 1 ...
// 4. 到了 rawMethod, rawMethod(n) + 1 + 1 + 1
console.log(z1(1))
var newMethod = applyMiddleWare(rawMethod, middleware3, middleware2)
// 调用顺序:middleware2 -> middleware3 -> rawMethod,结果:x=3
var x = newMethod(1)
console.log(x)
var newMethod2 = applyMiddleWare(newMethod, middleware1);
// 调用顺序:middleware1 -> middleware2 -> middleware3 -> rawMethod,结果:y=13
var y = newMethod2(10)
console.log(y)
7. 求某数在数组中最后出现的位置
实现一个函数,返回指定数在
有序
数组中最后出现的位置,要求时间复杂度O(logn)
7-1. 实现方式1
思路:
- 要求复杂度
O(logn)
那么就要不能使用简单的for循环,for循环时间复杂度O(n)
- 使用夹逼方式查找方式时间复杂度可以
- 夹逼方式简单介绍
- 分别取最大最小和中间值
- 查找目标如果在小到中,继续从小到中区间里面找,最大索引切换到中
- 同理,如果目标在中和大中间,继续从中到大区间找,最小缩影切换到中
- 不断重复,知道找到
- 目标等于小中大看情况做处理,这里因为找最后的位置,目标大等于中是就从中后面查找。
代码实现如下
function findLastIndex(arr, target) {
const len = arr.length;
let left = 0,
right = len - 1;
while (true) {
if (arr[left] > target || arr[right] < target) return -1;
if (arr[right] === target) {
return right;
}
if (left + 1 == right && arr[left] === target) {
return left;
}
let middle = Math.floor((right - left) / 2 + left);
if (arr[middle] <= target) {
left = middle;
} else if (arr[middle] > target) {
right = middle;
}
}
}
console.log(findLastIndex([1,2,3,3,3,4,5,7,8], 4));
最多一直查到左右两个碰到一起
7-2. 实现方式2
实际上就是取中间值使用了移位运算移动的是二进制,刚好结果就为需要的中间值
const findLastIndex = (nums, target) => {
const len = nums.length;
if (len < 1) return -1;
let l = 0,
r = len;
while (l < r) {
const mid = (l + r) >> 1;
target < nums[mid] ? (r = mid) : (l = mid + 1);
}
return l - 1;
};
console.log(findLastIndex([1, 3, 3, 3, 3, 5], 3));