Appearance
每日学习
JS基础
实现大数相加
js
const addStrings = (num1, num2) => {
let res = ''
let i = num1.length - 1
let j = num2.length - 1
let flag = 0
while(i >= 0 || j >= 0) {
let sum = flag;
if (i >= 0) sum += parseInt(num1[i--])
if (j >= 0) sum += parseInt(num2[j--])
flag = Math.floor(sum / 10)
res = sum % 10 + res;
}
if (flag > 0) {
res = flag + res;
}
return res;
};
console.log(addStrings("456231421242131414212", "45623142124213141421"));
const addStrings = (num1, num2) => {
let res = ''
let i = num1.length - 1
let j = num2.length - 1
let flag = 0
while(i >= 0 || j >= 0) {
let sum = flag;
if (i >= 0) sum += parseInt(num1[i--])
if (j >= 0) sum += parseInt(num2[j--])
flag = Math.floor(sum / 10)
res = sum % 10 + res;
}
if (flag > 0) {
res = flag + res;
}
return res;
};
console.log(addStrings("456231421242131414212", "45623142124213141421"));
实现Promise并发控制
js
async function asyncPool(limit, fns) {
const res = []
const exec = []
for (const item of fns) {
const p = Promise.resolve().then(() => item())
res.push(p)
if (limit <= fns.length) {
const execute = p.then(() => {
exec.splice(exec.indexOf(execute), 1)
})
exec.push(p)
console.log(exec.length)
if (exec.length >= limit) {
console.log('达到并发数量', limit)
await Promise.race(exec)
}
}
}
return Promise.all(res)
}
// 示例测试用例
async function runTest() {
const taskLimit = 3; // 最大并发数
const tasks = [
async () => {
await sleep(1000); // 模拟异步任务
console.log('执行完成 1');
return 1;
},
async () => {
await sleep(1000); // 模拟异步任务
console.log('执行完成 2');
return 2;
},
async () => {
await sleep(1000); // 模拟异步任务
console.log('执行完成 3');
return 3;
},
async () => {
await sleep(500); // 模拟异步任务
console.log('执行完成 4');
return 4;
},
async () => {
await sleep(2000); // 模拟异步任务
console.log('执行完成 5');
return 5;
},
async () => {
await sleep(1000); // 模拟异步任务
console.log('执行完成 6');
return 6;
},
async () => {
await sleep(3000); // 模拟异步任务
console.log('执行完成 7');
return 7;
},
async () => {
await sleep(500); // 模拟异步任务
console.log('执行完成 8');
return 8;
},
];
console.log(`Running asyncPool with a limit of ${taskLimit}`);
const results = await asyncPool(taskLimit, tasks);
console.log(`Results: ${results}`);
}
// 辅助函数,模拟异步任务
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// 运行测试用例
runTest().then(() => {
console.log('执行完毕');
}).catch(console.error);
async function asyncPool(limit, fns) {
const res = []
const exec = []
for (const item of fns) {
const p = Promise.resolve().then(() => item())
res.push(p)
if (limit <= fns.length) {
const execute = p.then(() => {
exec.splice(exec.indexOf(execute), 1)
})
exec.push(p)
console.log(exec.length)
if (exec.length >= limit) {
console.log('达到并发数量', limit)
await Promise.race(exec)
}
}
}
return Promise.all(res)
}
// 示例测试用例
async function runTest() {
const taskLimit = 3; // 最大并发数
const tasks = [
async () => {
await sleep(1000); // 模拟异步任务
console.log('执行完成 1');
return 1;
},
async () => {
await sleep(1000); // 模拟异步任务
console.log('执行完成 2');
return 2;
},
async () => {
await sleep(1000); // 模拟异步任务
console.log('执行完成 3');
return 3;
},
async () => {
await sleep(500); // 模拟异步任务
console.log('执行完成 4');
return 4;
},
async () => {
await sleep(2000); // 模拟异步任务
console.log('执行完成 5');
return 5;
},
async () => {
await sleep(1000); // 模拟异步任务
console.log('执行完成 6');
return 6;
},
async () => {
await sleep(3000); // 模拟异步任务
console.log('执行完成 7');
return 7;
},
async () => {
await sleep(500); // 模拟异步任务
console.log('执行完成 8');
return 8;
},
];
console.log(`Running asyncPool with a limit of ${taskLimit}`);
const results = await asyncPool(taskLimit, tasks);
console.log(`Results: ${results}`);
}
// 辅助函数,模拟异步任务
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// 运行测试用例
runTest().then(() => {
console.log('执行完毕');
}).catch(console.error);
实现Promise串行
js
async function serial(...args) {
return args.reduce((p, item) => p.then(() => item),Promise.resolve())
}
async function serial(...args) {
return args.reduce((p, item) => p.then(() => item),Promise.resolve())
}
实现Promise常见的方法
js
Promise.resolve = function(value) {
return new Promise((resolve, reject) => {
resolve(value)
})
}
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
Promise.all = function(promises) {
const result = []
let count = 0;
return new Promise((resolve, reject) => {
for (let i = 0;i < promises.length;i++) {
promises[i].then((value) => {
result[i] = value;
count++
if (count >= promises.length) {
resolve(result)
}
}, reject);
}
})
}
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
for (let i = 0;i < promises.length;i++) {
promises[i].then(resolve, reject)
}
})
}
Promise.deferred = function() {
const def = {}
def.promise = new Promise((resolve, reject) => {
def.resolve = resolve
def.reject = reject
})
return def;
}
Promise.allSettled = function(promises) {
const result = []
return new Promise((resolve) => {
for (let i = 0;i < promises.length;i++) {
promises[i].then((value) => {
result[i] = {
status: 'fullfilled',
value
}
}, (reason) => {
result[i] = {
status: 'reject',
reason
}
}).finally(() => {
if (i === promises.length - 1) {
resolve(result)
}
})
}
})
}
Promise.resolve = function(value) {
return new Promise((resolve, reject) => {
resolve(value)
})
}
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
Promise.all = function(promises) {
const result = []
let count = 0;
return new Promise((resolve, reject) => {
for (let i = 0;i < promises.length;i++) {
promises[i].then((value) => {
result[i] = value;
count++
if (count >= promises.length) {
resolve(result)
}
}, reject);
}
})
}
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
for (let i = 0;i < promises.length;i++) {
promises[i].then(resolve, reject)
}
})
}
Promise.deferred = function() {
const def = {}
def.promise = new Promise((resolve, reject) => {
def.resolve = resolve
def.reject = reject
})
return def;
}
Promise.allSettled = function(promises) {
const result = []
return new Promise((resolve) => {
for (let i = 0;i < promises.length;i++) {
promises[i].then((value) => {
result[i] = {
status: 'fullfilled',
value
}
}, (reason) => {
result[i] = {
status: 'reject',
reason
}
}).finally(() => {
if (i === promises.length - 1) {
resolve(result)
}
})
}
})
}
实现ajax请求
js
const xhr = new XMLHttpRequest()
xhr.open(method, url,true)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const text = xhr.responseText; // 获取响应内容
}
}
const xhr = new XMLHttpRequest()
xhr.open(method, url,true)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const text = xhr.responseText; // 获取响应内容
}
}
readyState 是 XMLHttpRequest 对象的一个属性,用来标识当前 XMLHttpRequest 对象处于什么状态。 readyState 总共有 5 个状态值,分别为 0~4,每个值代表了不同的含义
0:未初始化 -- 尚未调用.open()方法; 1:启动 -- 已经调用.open()方法,但尚未调用.send()方法; 2:发送 -- 已经调用.send()方法,但尚未接收到响应; 3:接收 -- 已经接收到部分响应数据; 4:完成 -- 已经接收到全部响应数据,而且已经可以在客户端使用了; 编辑此页面
实现apply和call
js
Function.prototype.call = function(context) {
context.fn = this;
const arr = []
for (let i = 1;i < arguments.length;i++) {
arr.push(`arguments[${i}]`)
}
const ret = eval(`context.fn(${arr})`)
delete context.fn;
return ret;
}
Function.prototype.apply = function (context, args) {
var context = context || window;
context.fn = this;
var res;
if (!args) {
res = context.fn();
} else {
const arr = [];
for (var i = 0; i < args.length; i++) {
arr.push("args[" + i + "]");
}
res = eval("context.fn(" + arr + ")");
}
delete context.fn;
return res;
};
Function.prototype.call = function(context) {
context.fn = this;
const arr = []
for (let i = 1;i < arguments.length;i++) {
arr.push(`arguments[${i}]`)
}
const ret = eval(`context.fn(${arr})`)
delete context.fn;
return ret;
}
Function.prototype.apply = function (context, args) {
var context = context || window;
context.fn = this;
var res;
if (!args) {
res = context.fn();
} else {
const arr = [];
for (var i = 0; i < args.length; i++) {
arr.push("args[" + i + "]");
}
res = eval("context.fn(" + arr + ")");
}
delete context.fn;
return res;
};
实现 asyncToGenerator
js
function asyncToGenerator(fn) {
return function() {
const gen = fn.bind(this, arguments)
return new Promise((resolve, reject) => {
function step(key, args) {
let res
try {
res = gen[next](args)
} catch(e) {
return reject(e)
}
const { value, done } = res;
if (done) {
return resolve(value)
} else {
return Promise.resolve(value).then(val => {
step('next', val)
}).catch((e) => {
step('throw', e);
});
}
}
step('next')
})
}
}
// 一个简单的 Generator 函数示例
function* exampleGenerator() {
yield new Promise((resolve) => setTimeout(() => resolve('Hello'), 1000));
yield new Promise((resolve) => setTimeout(() => resolve('World'), 1000));
}
// 使用 asyncToGenerator 转换 Generator 函数
const asyncFunction = asyncToGenerator(exampleGenerator);
// 使用转换后的 async 函数
asyncFunction()
.then((result) => console.log(result))
.catch((error) => console.error(error))
function asyncToGenerator(fn) {
return function() {
const gen = fn.bind(this, arguments)
return new Promise((resolve, reject) => {
function step(key, args) {
let res
try {
res = gen[next](args)
} catch(e) {
return reject(e)
}
const { value, done } = res;
if (done) {
return resolve(value)
} else {
return Promise.resolve(value).then(val => {
step('next', val)
}).catch((e) => {
step('throw', e);
});
}
}
step('next')
})
}
}
// 一个简单的 Generator 函数示例
function* exampleGenerator() {
yield new Promise((resolve) => setTimeout(() => resolve('Hello'), 1000));
yield new Promise((resolve) => setTimeout(() => resolve('World'), 1000));
}
// 使用 asyncToGenerator 转换 Generator 函数
const asyncFunction = asyncToGenerator(exampleGenerator);
// 使用转换后的 async 函数
asyncFunction()
.then((result) => console.log(result))
.catch((error) => console.error(error))
实现深拷贝
js
function getType(source) {
return Object.prototype.toString.call(source);
}
function deepCopy(source, memory) {
const isPrimitive = (value) => {
return /Number|Boolean|String|Null|Undefined|Symbol|Function/.test(
Object.prototype.toString.call(value)
);
};
let result;
memory || (memory = new WeakMap());
if (isPrimitive(source)) {
result = source;
} else if (Array.isArray(source)) {
result = source.map((value) => deepCopy(value, memory));
} else if (getType(source) === "[object Date]") {
result = new Date(source);
} else if (getType(source) === "[object Regex]") {
result = new Regex(source);
} else if (getType(source) === "[object Set]") {
result = new Set();
for (const value of source) {
result.add(deepClone(value, memory));
}
} else if (getType(source) === "[object Map]") {
result = new Map();
for (const [key, val] of source) {
result.set(key, deepCopy(val, memory));
}
} else {
if (memory.has(source)) {
result = memory.get(source);
} else {
result = Object.create(null);
memory.set(source, result);
Object.keys(source).forEach((key) => {
const value = source[key];
result[key] = deepClone(value, memory);
});
}
}
}
function getType(source) {
return Object.prototype.toString.call(source);
}
function deepCopy(source, memory) {
const isPrimitive = (value) => {
return /Number|Boolean|String|Null|Undefined|Symbol|Function/.test(
Object.prototype.toString.call(value)
);
};
let result;
memory || (memory = new WeakMap());
if (isPrimitive(source)) {
result = source;
} else if (Array.isArray(source)) {
result = source.map((value) => deepCopy(value, memory));
} else if (getType(source) === "[object Date]") {
result = new Date(source);
} else if (getType(source) === "[object Regex]") {
result = new Regex(source);
} else if (getType(source) === "[object Set]") {
result = new Set();
for (const value of source) {
result.add(deepClone(value, memory));
}
} else if (getType(source) === "[object Map]") {
result = new Map();
for (const [key, val] of source) {
result.set(key, deepCopy(val, memory));
}
} else {
if (memory.has(source)) {
result = memory.get(source);
} else {
result = Object.create(null);
memory.set(source, result);
Object.keys(source).forEach((key) => {
const value = source[key];
result[key] = deepClone(value, memory);
});
}
}
}
0.1+0.2为什么不等于0.3
在javascript中,Number类型使用的是IEEE754标准来表示浮点数,它会使用64位来存储一个浮点数。
而0.1和0.2的二进制是无限循环的,得出来的值也是无限循环,所以不等于0.3
QA: 如何求小数的二进制 0.625 * 2 = 1.25,所以第一位是1。 小数部分变为0.25。 0.25 * 2 = 0.5,所以第二位是0。 小数部分变为0.5。 0.5 * 2 = 1,所以第三位是1
let、var 和 const 的区别
WeakMap和Map的区别
- WeakMap的key只能是对象
- WeakMap无法遍历
- WeakMap没有
clear方法
- WeakMap没有
size属性
- 没有被引用的key,会被垃圾回收
axios如何取消请求
如果该请求已被发出,XMLHttpRequest.abort()
方法将终止该请求。当一个请求被终止,它的 readyState
将被置为 XMLHttpRequest.UNSENT (0)
,并且请求的 status 置为 0
。