JavaScript面试问题详解
嗨大家!👋 欢迎来到又一期免费的智慧分享 💡 (因为谁会不爱免费的智慧呢?)。你们可能在想,为什么还有一次分享?那是因为我写了一篇关于React面试问题的文章 💻,如果你是React开发者,强烈建议你去看看这篇文章。谢谢大家。 🙌
现在,让我们换一个方向,同样令人激动:JavaScript 面试题!庆祝一下!🎉 是的,那个充满了大括号 {}、棘手的语法、以及令人困惑的“为什么这是 undefined?”时刻的神奇世界。
如果你正在准备前端职位,JavaScript 将成为你新的最佳“ frenemy”。 😅面试官钟爱 JavaScript——可能是因为它广泛且深奥、难以预测,非常适合用来提出一些让你怀疑自己职业选择的问题,让你对自己的职业选择产生怀疑。😅
为了让大家更容易上手,并减少害怕,我把 JavaScript 的问题分成两大类 🍹:
理论: 🧠
啊,这是考验你哲学思想的部分。准备好迎接关于事件循环、继承,以及从“什么是原型?”到“为什么这恨我?”的各种问题吧。 🤔
特性编码: 🎨
这里才是重头戏。🌟 他们会要求你用 JavaScript 做一些酷炫的事情。可能是某个功能,也可能是一些有点奇怪的编码问题,比如涉及 setImmediate
或 setInterval
的问题。别紧张——我甚至还给你举个我自己面试时遇到的例子。这是深入了解 Promise 和 async/await 的绝佳机会,同时也不免让你怀疑自己当初的选择。��称漩涡🌀
所以,坐稳了!这将是一趟疯狂的JavaScript之旅。🚀
请注意:我只提了必须知道的问题
JavaScript 理论题:
1. 在JavaScript中存在哪些不同的数据类型?
2. 你能解释一下JavaScript中的Hoisting吗?
悬挂作用对箭头函数和普通函数有所不同。普通函数会被完全提升,这意味着它们的名字和定义都会被提升到作用域的顶部。相比之下,箭头函数不会被完全提升,因为它们通常会赋值给变量。只有变量会被提升,而箭头函数本身不会被提升。
3. var
,let
和 const
之间的区别是什么?这些是 JavaScript 中的关键字。
4. 所谓的值传递和引用传递在编程中是什么?
所有基本数据类型都是按值传递(传递的是值的副本),而非基本数据类型则是按引用传递(传递的是对象引用的副本)。
5. 深拷贝和浅拷贝有什么区别?
6. 什么是自执行函数,也就是立即调用的函数表达式(IIFE),也称为匿名函数?
(function () {
console.log("这是一个自调用函数" );
})();
按全屏 退出全屏
7. JavaScript 中的"严格模式"是什么意思?
8. 解释一下 JavaScript 中的高阶函数。
9. 解释一下 JavaScript 中的 this
关键字。
10. 解释一下 JavaScript 中的 call()
、apply()
和 bind()
方法。
11. 什么是 JavaScript 中的柯里化函数?
12. 什么是 JavaScript 中的词法作用域?
13. 解释一下 JavaScript 中的闭包的概念。
14. 什么是对象原型?
15. 什么是原型继承?
16. 什么是 JavaScript 中的回调函数?
17. 解释一下回调地狱。
18. 什么是剩余参数(...args),它与扩展运算符(...items)有何不同?
19. 在 JavaScript 中,Promise 的用途是什么?
20. 什么是生成器函数?
21. 什么是 JavaScript 中的暂时死区?
22. 什么是 JavaScript 中的 async
和 await
?
23. 解释一下 JavaScript 中的 reduce()
函数。
24. 什么是 JavaScript 中的隐式类型转换?
25. 为什么函数是“一等公民”?
26. 解释一下对象内的this
作用域。
如果一个函数位于一个对象内部,this
就指向该对象,就可以访问它的属性。
如果 this
在嵌套的函数或对象内部使用,它将指向最外层的对象,这通常是全局 window 对象。
27. new
关键字在JavaScript中的重要性是什么?
28. JavaScript中的memoization是什么意思?
29. JavaScript中的Map
、WeakMap
以及WeakSet
是什么?
30. JavaScript中的事件冒泡机制是什么?
31. JavaScript中的事件委托机制是什么?
32. JavaScript中的事件循环机制是什么?
33. JavaScript中的程序流程控制是什么?
在JavaScript中,控制流程控制着代码中语句的执行顺序。下面来看看一些主要的控制流程结构:if结构、if-else结构、switch结构、使用三元运算符、for循环结构。
34. 服务器端渲染(SSR)和客户端渲染(CSR)的区别是什么?
35. 声明式编程方式和过程式编程的区别是什么?
声明式编程(Declarative Programming):描述要达成的目标,侧重于期望的成果而非实现它的具体步骤。
指令式编程:描述如何做到,指定实现目标的具体步骤。
36. 什么是防抖和节流?(防抖和节流的含义是什么?)
基于特性的问答题:
1. 如何用 JavaScript 反转字符串?
const reversestring = str => str.split("").reverse().join("");
const res = reversestring("tpircsavaJ iH")
console.log(res) // 输出:Hi Javascript
点击全屏观看 点击退出全屏
2. 编写防抖处理代码。
<input placeholder="输入内容" id="userInput"/>
全屏模式 退出全屏
const inputBox = document.getElementById('userInput');
inputBox.addEventListener('input', (event) => {
Debouncing(event);
});
let interval;
function Debouncing (event) {
clearTimeout(interval);
interval = setTimeout(() => {
console.log(event.target.value);
}, 2000);
}
进入全屏模式,退出全屏模式
3. —— 实现限流
<input placeholder="请输入内容" id="userInput"/>
切换到全屏 切换回正常模式
const inputBox = document.getElementById('userInput');
inputBox.addEventListener('input', (event) => {
Throttling(event);
});
let value = true;
// 此函数用于限制输入事件的频率
function Throttling(event) {
if (value === true) {
console.log(event.target.value);
value = false;
setTimeout(() => {
value = true;
}, 2000);
}
}
进入全屏 退出全屏
4. 如何根据键值对对象的数组进行排序?
const array = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 20 }
];
// 按年龄升序排序
array.sort((a, b) => a.age - b.age);
console.log(array);
// 输出如下:
// [
// { name: 'Charlie', age: 20 },
// { name: 'Alice', age: 25 },
// { name: 'Bob', age: 30 }
// ]
全屏模式 退出全屏
5. 写一个构造函数,
function Person(name, age, city) {
// 名称
this.name = name;
// 年龄
this.age = age;
// 城市
this.city = city;
// 方法:
this.greet = function () {
console.log(`Hi, I'm ${this.name}, and I live in ${this.city}.`);
};
}
// 创建实例:
const person1 = new Person("Prajesh", 25, "Pune");
const person2 = new Person("Anjali", 28, "Mumbai");
// 使用:
person1.greet(); // 输出:
person2.greet(); // 输出:
切换到全屏模式,退出全屏
6. 请实现 map
、reduce
和 filter
的 polyfill(请参考上下文理解此术语)。
在这里,polyfill(兼容性填充)是一段代码,它模拟的是新功能或特性,使这些新功能能在不原生支持它们的环境中也能使用。
- 地图
Array.prototype.myMap = function(callback) {
if (!this || !Array.isArray(this)) {
throw new TypeError('myMap 只能在数组上使用。');
}
const result = [];
for (let i = 0; i < this.length; i++) {
if (this.hasOwnProperty(i)) {
result.push(callback(this[i], i, this));
}
}
return result;
};
// 示例代码
const numbers = [1, 2, 3];
const doubled = numbers.myMap((num) => num * 2);
console.log(doubled); // 输出结果为: [2, 4, 6]
切换到全屏 退出全屏
- 减少吧
Array.prototype.myReduce = function(callback, initialValue) {
if (!this || !Array.isArray(this)) {
throw new TypeError('myReduce 只能在数组上使用。');
}
if (typeof callback !== 'function') {
throw new TypeError('回调必须是函数。');
}
let accumulator = initialValue;
let startIndex = 0;
if (accumulator === undefined) {
if (this.length === 0) {
throw new TypeError('空数组没有初始值时不能调用 reduce。');
}
accumulator = this[0];
startIndex = 1;
}
for (let i = startIndex; i < this.length; i++) {
if (this.hasOwnProperty(i)) {
accumulator = callback(accumulator, this[i], i, this);
}
}
return accumulator;
};
// 自定义的 myReduce 方法
// 示例
const sum = [1, 2, 3, 4].myReduce((acc, num) => acc + num, 0);
console.log(sum); // 输出: 10
全屏 退出全屏
- 过滤
Array.prototype.myFilter = function(callback) {
if (!this || !Array.isArray(this)) {
throw new TypeError('myFilter 只能在数组上被调用。');
}
if (typeof callback !== 'function') {
throw new TypeError('回调必须是一个回调函数。');
}
const result = [];
for (let i = 0; i < this.length; i++) {
if (this.hasOwnProperty(i) && callback(this[i], i, this)) {
result.push(this[i]);
}
}
return result;
};
// 示例使用方法
const numbers = [1, 2, 3, 4];
const evens = numbers.myFilter((num) => num % 2 === 0);
console.log(evens); // 输出结果为: [2, 4]
进入全屏;退出全屏
7. 编写三个函数,分别延迟执行 3 秒、2 秒和 1 秒。接下来,使用 setTimeout
编写一个函数,按照一、二、三的顺序执行这三个函数,使输出如下:
1
2
3
全屏模式,退出全屏
const one = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("one")
resolve();
}, 3000)
})
}
const two = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("two")
resolve();
}, 2000)
})
}
const three = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("three")
resolve();
}, 1000)
})
}
const check = async () => {
await one();
await two();
await three();
}
check();
// 结果如下:
// one
// two
// three
进入全屏模式 退出全屏模式
8. 写一个简单的回调函数?
// 一个接受回调函数作为参数的函数方法
function greetUser(name, callback) {
console.log(`Hello, ${name}!`);
callback();
}
// 回调函数如下
function displayMessage() {
console.log('欢迎来到平台!');
}
// 调用greetUser函数时传入回调函数
greetUser('John', displayMessage);
进入全屏模式。退出全屏。
9. 编写一个乘法函数,该函数在使用下面的语法调用时能正常工作。
console.log(multiply(2)(3)(4)) // 结果为: 24
console.log(multiply(3)(4)(5)) // 结果为: 60
全屏 退出全屏
function multiply (x) {
return function (y) {
return function (z) {
return x * y * z; // 返回 x, y, z 三个数的乘积
}
}
}
点击全屏按钮进入全屏模式;点击退出按钮退出。
10. 写一段记忆化代码。
const memoizeAddition = () => {
let cache = {};
return (value) => {
if (value in cache) {
console.log("正在从缓存中获取");
return cache[value]; // 这里,因为属性名以数字开头,不是有效的 JavaScript 标识符,所以只能使用方括号表示法来访问。
} else {
console.log("正在计算结果");
let result = value + 20;
cache[value] = result;
return result;
}
};
};
// memoizeAddition 函数返回的函数
const addition = memoizeAddition();
console.log(addition(20)); // 输出:40(计算得出)
console.log(addition(20)); // 输出:40(来自缓存)
切换到全屏 退出全屏
祝贺你读到了这篇帖子的最后,非常感谢你的阅读,真的!
🎉 你的学习JavaScript的努力真是令人佩服。既然你已经看到这里,我想分享一个我在JavaScript学习过程中发现的非常棒的GitHub仓库。里面充满了宝贵的见解和资源,能帮助你更深入地了解JavaScript。相信我,你一定会喜欢的!
👉 代码库链接: https://github.com/sudheerj/javascript-interview-questions
共同学习,写下你的评论
评论加载中...
作者其他优质文章