文章目录
1.多维数组转为一维数组
let firstArr = [1, [2, [[3, 4], 5], 6]]
1.1 使用递归
思路:循环数组每一项,如果是数组类型,则递归,否则,放到新数组里
let finalArr = []
function deepArr(a) {
for (let i = 0; i < a.length; i++) {
if (Array.isArray(a[i])) {
deepArr(a[i])
} else {
finalArr.push(a[i])
}
}
}
deepArr(firstArr)
console.log(finalArr)
1.2 使用数组reduce方法
数组 reduce 方法,包含四个参数:
- perviousValue:上一次的计算结果的返回值
- currentValue:数组中正在处理的元素。若指定了初始值,则值则为数组索引为 0 的元素,否则为 1
- currentIndex:数组中正在处理的元素的索引。若指定了初始值,则起始索引为 0,否则为 1
- array:被遍历的对象数组
initialValue(可选):此参数作为第一次调用函数时参数 previousValue 的值,
若指定了初始值 initialValue,则 currentValue 则将使用数组第一个元素;
否则 perviousValue 将使用数组的第一个元素,而 currentValue 将使用数组第二个元素
const flatten = arr => arr.reduce(
(acc, val) => acc.concat(Array.isArray(val) ? flatten(val) : val), []
)
console.log(flatten(arr))
1.3 使用join,split
思路:将数组转换为字符串,再转换回来
问题:转换之后元素都为字符串类型
let finalArr=arr.join(',').split(',')
console.log(finalArr)
1.4 使用apply
问题:只能将二维数组改为一维
const arr = [1,[2,3],[4,5]];
console.log([].concat.apply([],arr));
2 数组去重
let arr=[11,22,33,44,55,66,77,88,33,22,44,11]
2.1 使用es6新增的set集合
let final=new Set(arr)
2.2 利用indexOf只能查到第一次出现的下标
let newArr=[]
let newArr = arr.filter((item, index) => {
return arr.indexOf(item) == index
})
2.3 for循环+indexOf
indexOf(或includex)判断新数组里是否存在,不存在则push
function duplicate(arrT) {
let newArr = []
for (let i = 0; i < arrT.length; i++) {
if (newArr.indexOf(arrT[i]) == -1) {
newArr.push(arrT[i])
}
}
return newArr
}
console.log( duplicate(arr))
2.4 双层for循环
function noRepeat(arr) {
for(var i = 0; i < arr.length-1; i++){
for(var j = i+1; j < arr.length; j++){
if(arr[i]===arr[j]){
arr.splice(j,1);
j--;
}
}
}
return arr;
}
console.log(noRepeat(arr12))
3.手写类
3.1 防抖
指触发事件后在n秒内函数只执行一次,如果在n秒内又重新触发了该事件,那么将会重新计算函数执行的时间。
场景:登录、提交按钮,发送短信等 防止多次提交
function debounce(fn, wait) {
var timeout = null;
return function() {
if(timeout !== null)
clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
// 处理函数
function handle() {
console.log(Math.random());
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));
3.2 节流
思路:保证一个时间一定时间内只执行一次,若有事件正在执行,则return。
场景:
- 鼠标连续不断地触发某事件(如点击),单位时间内只触发一次
- 监控浏览器resize
function throttle(fn, delay) {
let canRun = true; // 通过闭包保存一个标记
return function () {
// 在函数开头判断标记是否为true,不为true则return
if (!canRun) return;
// 立即设置为false
canRun = false;
// 将外部传入的函数的执行放在setTimeout中
setTimeout(() => {
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。
// 当定时器没有执行的时候标记永远是false,在开头被return掉
fn.apply(this, arguments);
canRun = true;
}, delay);
};
}
function sayHi(e) {
console.log('节流:', e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi, 500));
3.3 不含有重复字符串的最长子串(蚂蚁)
例:
input: abcabcbb output: 3
input: bbbbb output: 1
input: iwwkee output : wke 3
自己实现:
function solution(str){
let finalSet=new Set()
let finalLength=0
for(let i=0;i<str.length;i++){
if(!finalSet.has(str[i])){
finalSet.add(str[i])
finalLength++
}
}
return finalLength
}
let s='asdftya'
console.log(solution(s))
参考答案:
function solution(str: string): number {
let set = new Set()
let length = 0
let maxLength = 0
for (let i = 0; i < str.length; i++) {
if (!set.has(str[i])) {
//不存在
set.add(str[i])
length++
} else {
//存在
maxLength = Math.max(maxLength, length)
length = 0
}
}
return maxLength
}
3.4 给定一个二维数组,转换为对象(达摩院)
Input : [
["John", 12],
["Jack", 13],
["Matt", 14],
["Maxx", 15]
]
Output : {
"John": 12,
"Jack": 13,
"Matt": 14,
"Maxx": 15
}
实现:
function handleArr(arr) {
let finalObj={
}
for (let i = 0; i < arr.length; i++) {
let item = arr[i]
finalObj[item[0]]=item[1]
}
return finalObj
}
console.log(handleArr(Input))
3.5 手写promise
3.6 手写instanceof
b instance a :判断b是否为a的实例
即:b的原型指向a的prototype
实现:
//迭代实现
function instanceOf(obj, constructor) {
//取constructor的原型
let prototype = constructor.prototype;
//取obj的原型
obj = obj.__proto__;
while (true) {
if (obj === prototype)
return true;
obj = obj.__proto__;
if (obj === null)
return false;
}
}
3.7 深拷贝
1.Object.assign(空对象名,要复制的对象名)
一层实现(深拷贝),2、多层实现(浅拷贝))
2.JSON.parse
函数、undefined无法拷贝
3.手写方法
JSON.parse(JSON.stringify())
function deepClone(obj) {
if (typeof obj !== 'object') {
//简单数据类型直接返回
return obj
}
let newObj = {
}
for (let i in obj) {
newObj[i] = deepClone(obj[i])
}
return newObj
}
升级版:
function deepClone(obj) {
if (obj === null) return null; //null 的情况
if (obj instanceof RegExp) return new RegExp(obj); //正则表达式的情况
if (obj instanceof Date) return new Date(obj); //日期对象的情况
if (typeof obj == 'Function') return new function(obj){
}; //函数的情况
if (typeof obj != "object") {
//非复杂类型,直接返回 也是结束递归的条件
return obj
}
//[].__proto__.constructor=Array() []
//{}.__proto__.constructor=Object() {}
//因此处理数组的情况时,可以取巧用这个办法来new新对象
var newObj = new obj.__proto__.constructor;
for (var key in obj) {
newObj[key] = deepClone(obj[key])
}
return newObj;
}
3.8 跳马(字节二面)
代码:
// 注意象棋棋盘是7 * 7,然后象棋每次跳日
// let count = 0
function solution(x0, y0, xn, yn, n) {
// 递归出口
if (n == 0) {
if (x0 == xn && y0 == yn) {
// count++
return 1
}
return 0
}
let arr = getNextSteps(x0, y0)
let sum = 0
console.log(arr);
for (let i = 0; i < arr.length; i++) {
sum += solution(arr[i][0], arr[i][1], xn, yn, n - 1)
}
return sum
}
let c = solution(0, 0, 5, 6, 5)
// console.log(count);
console.log(c);
// 用于判断它的下一步跳的情况,在最中间时一共有8种跳跃情况
function getNextSteps(x, y) {
let arr = []
// 往第一象限跳
if (x <= 4 && y >= 1) {
arr.push([x + 2, y - 1])
}
if (x <= 5 && y >= 2) {
arr.push([x + 1, y - 2])
}
// 往第二象限跳
if (x >= 2 && y >= 1) {
arr.push([x - 2, y - 1])
}
if (x >= 1 && y >= 2) {
arr.push([x - 1, y - 2])
}
// 往第三象限跳
if (x >= 2 && y <= 5) {
arr.push([x - 2, y + 1])
}
if (x >= 1 && y <= 4) {
arr.push([x - 1, y + 2])
}
// 往第四象限跳
if (x <= 4 && y <= 5) {
arr.push([x + 2, y + 1])
}
if (x <= 5 && y <= 4) {
rr.push([x + 1, y + 2])
}
return arr
}
// let arr = getNextSteps(0, 0)
// console.log(arr);
3.9 获取url参数
给定一个url:
“http://www.baidu.com?name=张三&age=25&sex=男&wife=小红”
输出图片结果:
let URL = "http://www.baidu.com?name=张三&age=25&sex=男&wife=小红"
function getUrlParams(url) {
// 通过 ? 分割获取后面的参数字符串
let urlStr = url.split('?')[1]
// 创建空对象存储参数
let obj = {
};
// 再通过 & 将每一个参数单独分割出来
let paramsArr = urlStr.split('&')
for (let i = 0, len = paramsArr.length; i < len; i++) {
// 再通过 = 将每一个参数分割为 key:value 的形式
let arr = paramsArr[i].split('=')
obj[arr[0]] = arr[1];
}
return obj
}
console.log(getUrlParams(URL))
function handleUrl(u) {
let urlStr = u.split('?')[1]
let paramArr = urlStr.split('&')
let final = []
for (let i = 0; i < paramArr.length; i++) {
let item = paramArr[i].split('=')
final.push(item[0])
}
return final
}
console.log(handleUrl(URL))
3.10 第一个只出现一次的字符(美团)
在一个长字符串中找到第一个只出现一个的字符,并返回它的位置,如果没有则返回-1(需区分大小写),从0开始计数。
数据范围:0<=n<=10000,且字符串只有字母组成
要求:空间复杂度O(n) , 时间复杂度O(n)
示例:
输入 :"google"
输出:4
输入:"aa"
输出:-1
代码:
function handleFirst(s) {
for (let i = 0; i < s.length; i++) {
a = s.indexOf(s[i])
b = s.indexOf(s[i], a + 1)
if (b == -1) {
return i;
}
}
return -1;
}