3月25日远程前端开发面试题记录-猎头推的公司不知

83 阅读6分钟
  1. 给你一个数组里面是1-50的随机排列,用JS 写一个冒泡排序说说思路给出核心部分代码,按照降序
  2. 给你一个数组一到50,用js实现计算出 数组中a/b=5的元素
  3. 给你一个 字符串abbbccdef,js实现找出字符串中第一个不重复的字符串给出下标
  4. js实现一个识别回文字符串的方法
  5. js的数据类型有哪些,分别怎么判断
  6. js严格模式和普通模式谈谈 你的理解
  7. http和https的区别以及数据是如何加密的?加密协议有哪些?加密的方法有哪些 8.说说你对箭头函数和普通函数理解?区别和使用场景 这场面试节奏非常快,超过十秒没有反馈立马下一个问题,996,有时候晚上九点以后也要上班 其他不记得了,这几个印象深刻一点

1. 冒泡排序(降序)

思路

  • 遍历数组,每次比较相邻两个元素,如果前者小于后者,则交换它们的位置。
  • 每次遍历都会将本轮最大的元素冒泡到最后,不断缩小未排序部分的范围,直到数组完全有序。

核心代码

function bubbleSortDesc(arr) {
    let len = arr.length;
    for (let i = 0; i < len - 1; i++) {
        for (let j = 0; j < len - 1 - i; j++) {
            if (arr[j] < arr[j + 1]) {
                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; // 交换
            }
        }
    }
    return arr;
}
let arr = Array.from({ length: 50 }, (_, i) => i + 1).sort(() => Math.random() - 0.5);
console.log(bubbleSortDesc(arr));

2. 计算数组中 a / b = 5 的元素

思路

  • 遍历数组,检查是否存在 a / b = 5,即 a = 5 * b,满足条件的元素存入结果数组。

代码

let arr = Array.from({ length: 50 }, (_, i) => i + 1);
let result = [];
arr.forEach(a => {
    if (arr.includes(a / 5)) {
        result.push([a, a / 5]);
    }
});
console.log(result);

3. 找出字符串中第一个不重复的字符索引

思路

  • 使用 Map 统计字符出现次数。
  • 再次遍历字符串,找到第一个 count === 1 的字符并返回索引。

代码

function firstUniqueChar(str) {
    let map = new Map();
    for (let char of str) {
        map.set(char, (map.get(char) || 0) + 1);
    }
    for (let i = 0; i < str.length; i++) {
        if (map.get(str[i]) === 1) return i;
    }
    return -1;
}

console.log(firstUniqueChar("abbbccdef")); // 0

4. 识别回文字符串

思路

  • 将字符串反转后与原字符串对比,如果相等,则是回文。

代码

function isPalindrome(str) {
    return str === str.split('').reverse().join('');
}
console.log(isPalindrome("racecar")); // true
console.log(isPalindrome("hello")); // false

5. JS 数据类型及判断方法

基本数据类型

  • Number
  • String
  • Boolean
  • Undefined
  • Null
  • Symbol
  • BigInt

引用数据类型

  • Object(包括 ArrayFunctionDateRegExpSetMap

判断方法

console.log(typeof 123); // "number"
console.log(typeof "abc"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof Symbol("s")); // "symbol"
console.log(typeof BigInt(10)); // "bigint"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof function(){}); // "function"
console.log(Object.prototype.toString.call([])); // "[object Array]"

6. 严格模式与普通模式

严格模式 ("use strict")

  • 禁止 this 绑定到 window(默认 this === undefined
  • 禁止使用 eval 作用域修改变量
  • 禁止变量未声明直接赋值
  • 禁止删除不可删除属性
  • 禁止 with 语句

普通模式

  • 允许 this 绑定到 window
  • 允许未声明变量直接赋值

示例

"use strict";
x = 10; // 报错:未声明变量

7. HTTP vs HTTPS 及加密

区别

  • HTTP 是明文传输,容易被窃听
  • HTTPS 使用 SSL/TLS 进行加密传输,确保数据安全

加密协议

  • SSL(已淘汰)
  • TLS(TLS 1.2、TLS 1.3)

加密方式

  • 对称加密(AES、DES):双方使用相同密钥
  • 非对称加密(RSA、ECC):公钥加密,私钥解密
  • 哈希加密(MD5、SHA):不可逆加密,防篡改

8. 箭头函数 vs 普通函数

箭头函数 vs 普通函数

JavaScript 中,箭头函数普通函数(传统 function 关键字定义的函数)有一些关键区别,主要体现在 this 绑定、arguments、构造函数 等方面。


1. 主要区别

(1) this 指向不同

  • 普通函数this 由调用方式决定,可能指向 window、某个对象或 undefined(严格模式)。
  • 箭头函数this 继承自外层作用域,不会被 callapplybind 重新绑定。

🔹 示例 1:对象方法中 this 绑定

const obj = {
    name: "JavaScript",
    normalFunc() {
        console.log(this.name); // this 指向 obj
    },
    arrowFunc: () => {
        console.log(this.name); // this 继承自外层,指向 window/undefined
    }
};

obj.normalFunc(); // JavaScript
obj.arrowFunc();  // undefined (浏览器中是 window.name)

🔹 示例 2:定时器中 this

function Timer() {
    this.seconds = 0;
    setInterval(function() {
        this.seconds++;
        console.log(this.seconds); // NaN (this 指向 window)
    }, 1000);
}
new Timer();

🔹 改进:使用箭头函数

function Timer() {
    this.seconds = 0;
    setInterval(() => {
        this.seconds++; // 继承外层 this
        console.log(this.seconds);
    }, 1000);
}
new Timer();

(2) arguments 处理不同

  • 普通函数arguments 对象,包含调用时传入的参数。
  • 箭头函数 没有 arguments,只能使用 剩余参数 (...args)

🔹 示例

function normalFunc() {
    console.log(arguments); // [1, 2, 3]
}

const arrowFunc = () => {
    console.log(arguments); // 报错:arguments is not defined
};

normalFunc(1, 2, 3);
arrowFunc(1, 2, 3);

🔹 改进(使用 ...args 替代 arguments

const arrowFunc = (...args) => {
    console.log(args); // [1, 2, 3]
};
arrowFunc(1, 2, 3);

(3) 不能用作构造函数

  • 普通函数 可以使用 new 关键字实例化对象。
  • 箭头函数 不能 用作构造函数,否则会报错。

🔹 示例

function Person(name) {
    this.name = name;
}
const p1 = new Person("Alice"); // ✅ 正常工作

const ArrowPerson = (name) => {
    this.name = name;
};
const p2 = new ArrowPerson("Bob"); // ❌ 报错:ArrowPerson is not a constructor

(4) callapplybind 不能改变 this

  • 普通函数 可以使用 callapplybind 显式改变 this
  • 箭头函数this 绑定不可更改

🔹 示例

function normalFunc() {
    console.log(this);
}
const arrowFunc = () => {
    console.log(this);
};

const obj = { name: "JS" };

normalFunc.call(obj);  // `this` 指向 obj
arrowFunc.call(obj);   // `this` 仍然是外层作用域(不会变)

2. 使用场景

✅ 适合使用箭头函数的场景

  1. 回调函数(定时器、数组方法、事件监听)
  2. 对象方法里避免 this 绑定错误
  3. 高阶函数(如 mapfilterreduce
  4. 类中的方法(避免 this 绑定问题)

🔹 示例:数组方法

const numbers = [1, 2, 3, 4];
const squares = numbers.map(num => num * num);
console.log(squares); // [1, 4, 9, 16]

🔹 示例:事件监听

const button = document.querySelector("button");
button.addEventListener("click", () => {
    console.log(this); // `this` 继承自外层,避免 `this` 绑定问题
});

✅ 适合使用普通函数的场景

  1. 对象的方法(如果需要 this 绑定)
  2. 构造函数
  3. 需要 arguments 参数
  4. 需要 callapplybind 绑定 this

🔹 示例:对象方法

const obj = {
    name: "JS",
    sayHello() {
        console.log(this.name);
    }
};
obj.sayHello(); // JS

🔹 示例:构造函数

function Person(name) {
    this.name = name;
}
const p = new Person("Alice");
console.log(p.name); // Alice

3. 结论总结

对比点普通函数 (function)箭头函数 (=>)
this 绑定调用时决定(动态)继承外层作用域
arguments✅ 有❌ 没有,可用 ...args 代替
new 关键字✅ 可以实例化对象❌ 不能用 new
call/apply/bind✅ 可以改变 this❌ 无法改变 this
适用场景构造函数、对象方法、复杂逻辑回调、数组方法、类方法

💡 总结

  1. 箭头函数的 this 继承外层作用域,不受 call/apply/bind 影响。
  2. 普通函数的 this 由调用方式决定,适用于对象方法、构造函数等。
  3. 箭头函数不能作为构造函数,不能使用 new 关键字。
  4. 箭头函数没有 arguments,需要用 ...args 代替。

💡 什么时候用箭头函数?
回调函数、数组方法、定时器、事件监听、类方法(避免 this 绑定问题)。

💡 什么时候用普通函数?
构造函数、对象方法、需要 argumentsthis 绑定的场景


希望这能帮助你理解箭头函数和普通函数的区别!如果有具体代码问题,欢迎继续交流~ 🚀