前端笔试题(持续更新中~~)

大家好,这篇文章我只写代码,如果有什么疑问,我们再评论区讨论。

数组

1、手写实现数组map

// array.map(function(currentValue, index, arr), thisValue)
Array.prototype._map = function(callback, thisArg) {
  const _mapArr = [];
  for (let i = 0; i < this.length; i++) {
    const mappedValue = callback.call(thisArg, this[i], i, this);
    _mapArr.push(mappedValue);
  }
  return _mapArr;
};

var numbers = [1, 2, 3, 4, 5];
const doubleNumbers = numbers._map(function(item) {
  return item * this.multiplier;
}, { multiplier: 2 });
console.log(doubleNumbers); // [2, 4, 6, 8, 10]

2、手写实现数组reduce

// array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
Array.prototype._reduce = function(callback) {
  var acc = this[0];
  for (var i = 1; i < this.length; i++) {
    acc = callback(acc, this[i], i, this);
  }
  return acc;
};

var numbers = [1, 2, 3, 4, 5];
var sum = numbers._reduce(function(total, currentValue) {
  return total + currentValue;
});
console.log(sum); // 15

3、数组filter

对象

1、Object.create()

function create(obj) {
  function F() {}
  F.prototype = obj
  return new F()
}

2、实现Object.assign

function create(obj) {
  function F() {}
  F.prototype = obj
  return new F()
}

扁平化

1、数组扁平化-手写实现数组flat

Array.prototype._flat = function() {
  return this.reduce(function(acc, currVal) {
    if (Array.isArray(currVal)) {
      return acc.concat(currVal._flat())
    } else {
      return acc.concat(currVal)
    }
  }, []);
};

var deepArray = [1, [2, [3, 4], 5]];
console.log(deepArray._flat()); // [1, 2, 3, 4, 5]

2、对象扁平化

function flattenObject(obj) {
  let result = {};

  function recurse(current, path) {
    for (let key in current) {
      if (current.hasOwnProperty(key)) {
        let newPath = path + (path ? '.' : '') + key;
        if (typeof current[key] === 'object') {
          recurse(current[key], newPath);
        } else {
          result[newPath] = current[key];
        }
      }
    }
  }

  recurse(obj, '');
  return result;
}

// 使用示例
let nestedObject = {
  a: {
    b: {
      c: 1,
      d: 2
    },
    e: 3
  },
  f: 4
};

let flattenedObject = flattenObject(nestedObject);
console.log(flattenedObject);

Promise

1、Promise:

2、promise.all()的实现

3、promise.race的实现

防抖 & 节流

防抖函数

function debounce(func, delay) {
  let timer;
  return function() {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, arguments);
    }, delay);
  };
}

const debouncedEventHandler = debounce(function() {
  console.log('debounce')
}, 300);

节流函数

function throttle(func, delay) {
  let canExecute = true;
  return function() {
    if (!canExecute) return;
    canExecute = false;
    setTimeout(() => {
      func.apply(this, arguments);
      canExecute = true;
    }, delay);
  };
}

const throttledEventHandler = throttle(function() {
  console.log('throttle')
}, 300);

深拷贝

const originObj = { a: 1, b: { c: 2 } };

// 使用 `JSON.parse` 和 `JSON.stringify` 实现,适用于对象中不包含函数、`undefined` 等特殊值的情况。 
// const deepObj = JSON.parse(JSON.stringify(originObj));

// 递归实现
function deepCopy(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  const newObj = Array.isArray(obj) ? [] : {};

  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepCopy(obj[key]);
    }
  }

  return newObj;
}

const deepObj = deepCopy(originObj);
console.log(deepCopiedObject);

this

手写实现call

Function.prototype._call = function(context, ...args) {
  context = context || window; // 设置默认上下文为全局对象(window)
  const uniqueKey = Symbol(); // 创建一个唯一的键,以免与现有属性冲突
  
  context[uniqueKey] = this; // 将原函数赋值给上下文对象的一个临时属性
  const result = context[uniqueKey](...args); // 通过上下文对象调用原函数,传入参数
  
  delete context[uniqueKey]; // 删除临时属性,清理上下文对象

  return result;
};

function greet(name) {
  console.log(`Hello, ${name}! My name is ${this.name}.`);
}

const person = { name: 'John' };
greet._call(person, 'Alice'); // Hello, Alice! My name is John.

手写实现apply

// 自定义实现 apply
Function.prototype._apply = function(context, argsArray) {
  context = context || window; // 设置默认上下文为全局对象(window)
  const uniqueKey = Symbol(); // 创建一个唯一的键,以免与现有属性冲突

  context[uniqueKey] = this; // 将原函数赋值给上下文对象的一个临时属性
  const result = context[uniqueKey](...argsArray); // 通过上下文对象调用原函数,传入参数数组
 
  delete context[uniqueKey];  // 删除临时属性,清理上下文对象

  return result;
};

function sum(a, b) {
  return a + b + this.c;
}

const obj = { c: 3 };
const numbers = [1, 2];
const result = sum._apply(obj, numbers);   // 6
console.log(result); 

手写实现bind函数

其他

函数柯里化的实现

手写实现new操作符(没见过)

手写实现instanceof(没见过)

手写类型判断函数(没见过)

使用 setTimeout 实现 setInterval

实现 sleep 函数(没见过)

数据处理

1、发布-订阅模式

function sleep(time) {
  return new Promise((resolve) => {
    setTimeout(resolve, time)
  })
}

// 使用
async function test() {
  console.log('start')
  await sleep(2000)
  console.log('end')
}
test()

2、双向数据绑定

let obj = {}
let input = document.getElementById('input')
let span = document.getElementById('span')
// 数据劫持
Object.defineProperty(obj, 'text', {
  configurable: true,
  enumerable: true,
  get() {
    console.log('获取数据了')
  },
  set(newVal) {
    console.log('数据更新了')
    input.value = newVal
    span.innerHTML = newVal
  }
})
// 输入监听
input.addEventListener('keyup', function(e) {
  obj.text = e.target.value
})

3、数组转树形(Tree)结构

// 构建了一个节点映射(map),然后遍历数组两次,一次用于构建节点映射,另一次用于构建树结构。
function arrayToTree(data) {
  const map = {};
  const tree = [];

  data.forEach(item => {
    map[item.id] = { ...item, children: [] };
  });

  data.forEach(item => {
    if (item.parent_id !== 0) {
      map[item.parent_id].children.push(map[item.id]);
    } else {
      tree.push(map[item.id]);
    }
  });

  return tree;
}

const dataArray = [
  { "id": 12, "parent_id": 1, "name": "朝阳区" },
  { "id": 241, "parent_id": 24, "name": "田林街道" },
  { "id": 31, "parent_id": 3, "name": "广州市" },
  { "id": 13, "parent_id": 1, "name": "昌平区" },
  { "id": 2421, "parent_id": 242, "name": "上海科技绿洲" },
  { "id": 21, "parent_id": 2, "name": "静安区" },
  { "id": 242, "parent_id": 24, "name": "漕河泾街道" },
  { "id": 22, "parent_id": 2, "name": "黄浦区" },
  { "id": 11, "parent_id": 1, "name": "顺义区" },
  { "id": 2, "parent_id": 0, "name": "上海市" },
  { "id": 24, "parent_id": 2, "name": "徐汇区" },
  { "id": 1, "parent_id": 0, "name": "北京市" },
  { "id": 2422, "parent_id": 242, "name": "漕河泾开发区" },
  { "id": 32, "parent_id": 3, "name": "深圳市" },
  { "id": 33, "parent_id": 3, "name": "东莞市" },
  { "id": 3, "parent_id": 0, "name": "广东省" }
];

const treeData = arrayToTree(dataArray);
console.log(JSON.stringify(treeData, null, 2));

算法题

字符串出现的不重复最长长度

小孩报数问题

有30个小孩儿,编号从1-30,围成一圈依此报数,1、2、3 数到 3 的小孩儿退出这个圈, 然后下一个小孩 重新报数 1、2、3,问最后剩下的那个小孩儿的编号是多少?

function childNum(num, count){
    let allplayer = [];    
    for(let i = 0; i < num; i++){
        allplayer[i] = i + 1;
    }
    
    let exitCount = 0;    // 离开人数
    let counter = 0;      // 记录报数
    let curIndex = 0;     // 当前下标
    
    while(exitCount < num - 1){
        if(allplayer[curIndex] !== 0) counter++;    
        
        if(counter == count){
            allplayer[curIndex] = 0;                 
            counter = 0;
            exitCount++;  
        }
        curIndex++;
        if(curIndex == num){
            curIndex = 0               
        };           
    }    
    for(i = 0; i < num; i++){
        if(allplayer[i] !== 0){
            return allplayer[i]
        }      
    }
}
childNum(30, 3)

统计一个字符串出现最多的字母

输入 : afjghdfraaaasdenas

输出 : a
前面出现过去重的算法,这里需要是统计重复次数。

function findMostFrequentLetter(str) {
    // 将字符串转换为小写以进行不区分大小写的统计
    const lowerCaseStr = str.toLowerCase();

    // 创建一个对象来存储每个字母的出现次数
    const charCount = {};

    // 遍历字符串并统计每个字母的出现次数
    for (let i = 0; i < lowerCaseStr.length; i++) {
        const char = lowerCaseStr[i];
        if ((char >= 'a' && char <= 'z')) {  // 仅考虑字母
            charCount[char] = (charCount[char] || 0) + 1;
        }
    }

    // 找到出现次数最多的字母
    let mostFrequentChar = '';
    let maxCount = 0;

    for (let char in charCount) {
        if (charCount[char] > maxCount) {
            mostFrequentChar = char;
            maxCount = charCount[char];
        }
    }

    return mostFrequentChar;
}

// 示例
const inputString = "afjghdfraaaasdenas";
const result = findMostFrequentLetter(inputString);
console.log(result);  // 输出:a
  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值