JavaScript 面试高手:热门问题解析
JavaScript 面试并非易事,许多应聘者花费了无数时间钻研零散的编程题,才建立起自信。虽然大量的练习至关重要,但练习的方式也至关重要。制定一个结构化的计划,能帮助你掌握面试官期望的所有基础和高级概念。
为了让您熟悉面试准备过程和您需要了解的问题,我们编制了一份需要了解的概念以及实用的编码解决方案的有序列表。
今天,我们将讨论:
如何准备 JavaScript 面试
编程面试极其严格,很多应聘者都不知该如何准备。现实情况是,JavaScript 面试没有万能的灵丹妙药,关键在于准备的充分程度和准备的深度。Educative 深谙编程面试准备之道,因此我们想带你了解一下这个久经考验的准备策略。现在就开始吧!
第一步:了解你需要学习什么
你已经知道要使用哪种编程语言,所以现在你需要研究一下要测试该语言的哪些方面。这一步包含三个方面:
了解你面试的级别。初级开发人员职位不太可能要求你了解很多并发知识。高级开发人员职位很可能会考察你的系统设计能力。提前了解面试的级别,能让你更好地专注于重要的事情。我们都知道,这些级别可能比较随意,但了解公司的组织架构能让你更有竞争力。
了解面试会考察哪些技能。JavaScript是一门庞大的语言,拥有多个版本和看似无限的功能。但并非所有技能都会在面试中被考查。了解面试通常包含哪些技术技能也很重要。例如,你可能知道,数据结构和算法在面试中经常出现,而基础的语言问题则较少出现。
了解组织的期望。有些公司对技能的要求与其他公司不同。有些公司更注重某些 JavaScript 工具。你需要了解组织对你的期望。你可以在他们的公司网站、职位描述或类似Coding Interview的网站上进行研究。根据组织的要求准备,可以节省时间和精力。
第二步:制定计划
很多人会忽略这一步,导致准备工作变得零散。提前制定计划可以确保你涵盖所有需要的内容,并让你更有动力。一般来说,你需要三个月的时间来准备编程面试。
有很多内容需要学习,你肯定不想最后一刻才临时抱佛脚。留出足够的时间,并在学习初期制定计划。
我们整理了一份备考路线图,为期三个月,深受大家喜爱,可供您参考制定计划。这份路线图将首先帮助您温习基础知识,然后逐步学习数据结构和算法,最后深入探讨更复杂的概念。
重要的是不要跳过最初的复习或练习。很多人没有复习 JavaScript 的基本原理,最终在面试时不知所措。从基础到复杂,你的学习会更有针对性,也更自然。
请参阅本文,了解制定面试准备计划的五个行之有效的技巧。
第三步:不要忘记行为面试
编程面试会伴随行为面试。面试官会通过这一环节了解你的个人情况,并考察你的价值观是否符合他们的公司。这些面试对于最终的录用至关重要。许多求职者忘记了行为面试的准备,而只关注技术技能。
这是一个大错误。
虽然行为面试的准备时间较短,但它对你的成功仍然至关重要,应该在你的计划中有所体现。想了解更多关于行为面试的信息,请查看这篇文章,它将带你全面了解整个面试流程。
现在您已经了解了如何准备面试,让我们深入了解面试中可能遇到的最重要的 JavaScript 问题。
关于 JavaScript 语言基础的问题
提升
高级或初级水平的学生可能会问到关于代码提升的问题。为了测试你对 JavaScript 代码提升的理解,你可能会被问到这样的问题:
以下代码的输出是什么?
function Add(){
console.log(answer)
var answer = 2
};
Add()
输出:未定义
在 JavaScript 中,我们可以在使用变量之后再声明它,因为变量声明var
在编译时会被提升到其功能作用域的顶部。这意味着变量可以在声明之前初始化。我们来看另一个例子。
注意:只有声明会被提升到顶部,初始化则不会。
var temp = "hi"
function display(){
var temp
console.log(temp)
temp = "bye"
}
display()
这里,var temp = ‘bye’
是一个函数作用域变量。它的声明在编译时var temp
被提升到函数顶部。由于其值位于第 4 行之后,因此输出为 undefined。display( )
bye
检查括号
检查括号是否匹配是 JavaScript 面试中常见的问题。你可能会被问到这样的问题:
编写一个括号检查函数来确定输入字符串的左括号和右括号是否正确嵌套。
function balancedParentheses(str) {
let stack = [];
let map = {
'(': ')',
'[': ']',
'{': '}'
}
for (let i = 0; i < str.length; i++) {
// If character is an opening brace add it to a stack
if (str[i] === '(' || str[i] === '{' || str[i] === '[' ) {
stack.push(str[i]);
}
//if closing brace, pop from stack
else {
let lastEle = stack.pop();
//Return false if the element popped doesn’t match the corresponding closing brace in the map
if (str[i] !== map[lastEle]) {return false};
}
}
//if stack not empty at end, return false
if (stack.length !== 0) {return false};
return true;
}
console.log(balancedParentheses("{[]()}" ));
console.log(balancedParentheses("{[(])}"));
console.log(balancedParentheses("{[}"));
输出:真假假
这个问题的解决方案比看起来要简单。首先,我们在第 2 行声明一个堆栈,它保存了所有的左括号。然后,我们map
在第 3-6 行声明一个对象,它保存了三种类型的左括号及其对应的右括号。
然后,我们遍历在第 9 行传入函数的字符串表达式。如果当前字符是左括号,则将其压入堆栈。如果是右括号,则将pop
其从堆栈中取出。如果该字符与起始括号不匹配,则告诉程序返回false
。到达末尾时, 中剩余的左括号都stack
将返回false
。
数组解构
JavaScript 面试中,一个常见的题目是使用数组解构移除数组的前两个元素。我们来看看答案。
function removeFirstTwo(list) {
const [, , ...arr] = list;
return arr;
}
var arrLiteral = [8,9,10,11,12]
console.log("arr contains: " + removeFirstTwo(arrLiteral))
输出: arr 包含:10,11,12
析构数组的语法与数组字面量类似。在等式的左边,我们定义要从等式的右边检索哪些值。
const [value1, value2] = arrLiteral
让我们看看它是如何存储的。
var arrLiteral = [8,9,10,11,12]
const [value1, value2] = arrLiteral
console.log("value1 is: " + value1)
console.log("value2 is: " + value2)
输出:值1为:8 值2为:9
value1
将值存储在arrLiteral
、中8
,并将value2
其对应的值存储在arrLiteral
、中9
。我们可以使用逗号运算符跳过前两个值,
。因此,value1
和value2
存储接下来的两个值,10
和11
。
然后,我们可以使用 rest 参数将剩余的值收集到一个数组中。最后arr
返回。请看这里。arr
function removeFirstTwo(list) {
const [, , ...arr] = list;
return arr; // line 3 of original code
}
解构 undefined
这个常见的挑战要求你在 JavaScript 中进行解构undefined
。假设你输入一个point
变量,我们需要输出name
和age
属性的值。来看看吧。
function pointValues(point){
const {name:n,age:a} = {...point}
console.log(n)
console.log(a)
}
pointValues({name:"jerry", age:2})
pointValues(undefined)
如果它是一个对象,代码会显示name
和age
的值point
,从而报错undefined
。我们需要先将 展开point
成一个对象,然后才能解构它。
const {name:n,age:a} = {...point}
我们使用 来实现这一点{...point}
,它使用 的属性创建一个新对象point
。现在,新对象将包含所有相同的值,就像一种副本一样。值undefined
和null
会被忽略。当undefined
展开时,新对象中不会存储任何值,因此不会抛出任何错误。因此,undefined
当我们访问name
和时,我们可以看到这一点age
。
其他问题
还有许多其他 JavaScript 面试问题可以测试你对语言基础知识的了解。其中包括:
- 定义一个函数,
createPhoneNumber
它接受一个包含 10 个整数(从 0 到 9)的数组,并以电话号码的形式返回这些数字的字符串。 - 给定一个数组
coins
,编写一个函数来计算使用这些硬币可以制作该硬币的方法数amount
。 - 箭头函数与其他函数有何不同?
Function.call
和方法之间有何显著区别Function.apply
?- 是否可以在 JavaScript 中运行异步代码?
- 给定一个函数
returnNthCat
,该函数接受一个变量,并在其中定义了n
一个对象。返回第 th 个 cat 对象的值。state
name
n
如果您想查看其他常见的 JavaScript 语言问题或探索这些问题的解决方案,请查看课程《JavaScript 面试手册:100 多个面试问题》,以便亲身练习应对所有这些挑战及更多问题。
关于类型强制转换的问题
的实例
JavaScript 面试中一个常见的问题是关于instanceof
运算符的。你可能会遇到这样的问题:
下面的代码输出是什么?
var names = ["Tom","Anna",2,true]
console.log(names instanceof String)
console.log(names instanceof Number)
console.log(names instanceof Object)
console.log(names instanceof Array)
输出: false false true true
该instanceof
运算符检查操作数是右侧传递的对象的实例,还是其任何祖先的实例。答案false false true true
是正确的,因为我们使用的是一个数组,names
其中包含字符串、数字和布尔类型的值。
names
不是字符串或数字的实例,而是 的实例数组Array
。在 JavaScript 中,Array
是一个对象,因此names
也是 的实例Object
。
是否是阵列?
测试的一个常见问题如下:
实现一个函数check
,接受一个对象并判断它是否为数组。它应该返回true
或false
。
看一下答案:
function check(obj) {
if (Object.prototype.toString.call(obj) === "[object Array]") {
return true;
} else {
return false;
}
}
console.log(check(123));
console.log(check("cat"));
console.log(check([1, 2, 3, 4]));
输出: false false true
要检查一个对象是否为数组,我们必须使用Object.prototype.toString
方法,它以 的形式返回一个字符串[object Type]
。如果我们在 上调用它123
,我们将返回字符串[object Number
。如果我们在 上调用它{}
,我们将返回[object Object]
。如果我们在数组上调用它,我们应该返回[object Array]
。
在第 2 行,看看我们如何比较从 返回的字符串Object.prototype.toString
与[object Array]
。如果匹配,则返回true
,否则返回false
。
数组的实例?
这道题考察你对 的知识instanceof
,比较有技巧。请看下面的代码:
function check(){
var tempFunc = function () {}
return new tempFunc instanceof Array;
}
console.log(check())
输出: false
该check
函数包含 的定义tempFunc
,并且在第 4 行,我们检查 的实例是否tempFunc
是 的实例Array
。你的任务是在第 3 行编写代码,使语句返回true
。让我们分解一下解决方案。
function check(){
var tempFunc = function () {}
tempFunc.prototype = Array.prototype
return new tempFunc instanceof Array;
}
console.log(check())
输出: true
我们需要修改代码,使新对象成为数组的实例。我们需要进行修改,使Array.prototype
存在于 的原型链中tempFunc
。
tempFunc.prototype = Array.prototype //line 3
现在,我们将 设置tempFunc.prototype
为 等于Array.prototype
。它现在应该返回true
。
其他问题
还有许多其他 JavaScript 面试题可以测试你对类型强制转换的了解。这些面试题包括:
- 以下代码将显示什么?
console.log(Object.prototype.toString.call(new (function Custom(){})));
- 运营商的目的是什么
typeof
? typeof
使用JavaScript 中的运算符验证参数的技巧prototype.toString
使用箭头函数验证日期技能- 以及更多
关于 JavaScript 中的 OOP 的问题
isProtypeOf
这道题考察你使用isPrototypeOf
JavaScript 函数实现对象方法的能力。假设你得到以下代码:
function isPrototype(){
var obj1 = {x: 1};
var obj2;
console.log(
obj1.isPrototypeOf(obj2)
);
}
isPrototype()
输出: false
你将被要求编写代码,obj2
使语句true
在第 5 行返回。我们需要obj1
成为obj2
的原型链的一部分。我们可以使用该Object.create
函数来实现这一点,该函数会创建一个对象并将其存储在变量 中obj2
。
Object.create
将其作为参数并返回一个具有指向 的原型属性的对象obj1
。这构成了obj1
原型链,因此Object.getPrototypeOf(obj2)
将返回obj1
。
function isPrototype(){
var obj1 = {x: 1};
var obj2 = Object.create(obj1)
console.log(
obj1.isPrototypeOf(obj2)
);
}
isPrototype()
输出: false
ES6 类
ES6 技能在 JavaScript 面试中非常重要,因为它能证明你掌握了最新的 JavaScript 技能。假设你被要求编写以下代码:
function Cat (name) {
this.name = name
}
Cat.meow = function () {
console.log(this.name + ' says meow')
}
let catty = new Cat('catty')
catty.meow()
你会被要求修改代码来解决其错误,但你只能使用 ES6 类。此代码中的错误是由于meow
原型上未定义Cat
,因此它未被对象继承catty
。我们需要将其重新定义为原型,但将关键字替换function
为class
。
然后,我们可以constructor
在类内部定义一个name
作为参数。完成后,我们可以meow
在新类内部定义一个新方法,即,它meow
是的一部分Cat
。这样,它将继承所有方法,因此catty.meow()
不会导致错误。
class Cat {
constructor (name) {
this.name = name
}
meow () {
console.log(this.name + ' says meow')
}
}
let catty = new Cat('catty')
catty.meow()
输出: catty说喵呜
原型继承
由于 JavaScript 是基于原型继承的语言,因此你可能会遇到类似这样的问题来测试你的技能。假设你得到了以下代码:
function Human(name, age) {
this.name = name;
this.age = age;
};
function Man(name) {
};
function check(){
var obj = new Man("Tommy Tan");
console.log(obj.name)
console.log(obj instanceof Human)
}
check()
你需要在 类Human
和之间实现继承Man
。代码应该能够成功编译。我们来看看解决方案。
function Human(name, age) {
this.name = name;
this.age = age;
};
function Man(name,age) {
Human.call(this, name, age);
};
Man.prototype = Object.create(Human.prototype);
Man.prototype.constructor = Man;
function check(){
var obj = new Man("Tommy Tan",20);
console.log(obj.name)
console.log(obj instanceof Human)
}
check()
Human
是父级,子级Man
将继承它。为了Man
继承它的属性,我们必须在Man
的构造函数中调用父级的构造函数。这将初始化父级所需的成员,name
并且age
。
此过程允许obj
访问name
属性,因此您将看到name
而不是undefined
。第 10 行创建了一个原型链,这意味着 any 都Man
将以Human
作为其原型。现在,obj instanceof Human
将返回true
。
一旦我们将 设置Man.prototype
为Human
,它的构造函数指针就会指向它。我们通过constructor
在第 11 行将 属性设置为指向 Man 来纠正这个问题,但为了保留构造函数属性,这是可选的。
其他问题
还有许多其他 JavaScript 面试题可以测试你对面向对象 JavaScript 编程的了解。其中包括:
this
与关键字相关的问题 与关键字
相关的问题 ES5 和 ES6 之间的区别 从类创建对象实例 以下哪些是原生 JavaScript 对象? 对象在 JavaScript 中如何工作? 如何创建对象字面量? 等等super
如果您想了解有关 JavaScript 中面向对象编程的更多信息,请查看本指南以获取介绍或复习。
关于函数式编程的问题
纯函数
纯函数是一项重要的 JavaScript 技能。你可能会遇到类似这样的问题,它们会测试你的问题解决能力。
下面的代码中有一个非纯函数addAndPrint
。请将其修改为纯函数。
const addAndPrint = (a, b) => {
const sum = a+b;
console.log(`The sum is ${sum}`);
return sum;
};
const ans = addAndPrint(4,5)
输出:总和为 9
首先,你必须弄清楚为什么这个函数是不纯的。addAndPrint
看起来对外部状态没有负面影响。然而,console.log
语句却有一个副作用,它违反了结果不应该引起副作用的规则,例如可变对象的突变。我们必须通过移除 将其转换为纯函数console.log
。
请记住,函数执行的任何与计算最终输出无直接关系的工作都是副作用!
const addAndPrint = (a, b) => {
const sum = a+b;
return sum;
};
const ans = addAndPrint(4,5)
console.log("The sum is " + ans)
浅复制
你可能会遇到一些关于 JavaScript 浅拷贝的问题。假设你得到了下面的代码,并被要求给出它的输出。
const girl = {
name: 'Anna',
info: { age: 20, number: 123 }
};
const newGirl = { ...girl };
newGirl.info.age = 30;
console.log(girl.info.age, newGirl.info.age);
正确的输出是30 30
。为什么?因为该对象girl
具有属性name
和info
。我们使用扩展运算符将该对象的属性复制到 中newGirl
,从而创建了一个浅拷贝。两者共享一个引用,因为在 JavaScript 中对象是通过引用传递的。
这意味着,当你将一个对象赋值给一个变量时,它与该对象的标识相关联。当我们将 赋值girl
给 时newGirl
,newGirl
和 指向同一个对象girl
,因此它们的属性如果被改变,都会改变。
高阶函数
关于高阶函数的问题对于在 JavaScript 面试中脱颖而出至关重要。你可能会遇到这样的问题。
研究下面的代码。它是func1
一个高阶函数吗?
const func1 = function(num){
return function(){
if(typeof num == 'NaN'){
return "Not a number"
}else{
return typeof(num)
}
}
}
高阶函数是指那些接受函数作为参数或返回一个函数作为输出的函数。查看代码时,我们可以看到它func1
没有接受函数作为参数。然而,如果我们仔细查看第 2 行,我们会发现它确实返回了一个函数作为输出。因此,它是一个高阶函数。
其他问题
JavaScript 面试中还有许多其他问题可以测试你对函数式编程的了解。其中一些问题和概念可能是:
- 将非纯函数转换为纯函数,返回包含新属性的新对象
- 创建一个函数
maxCookies
,返回根据食谱可以烹制的完整饼干的最大数量 - 在 JavaScript 中实现 reduce 函数
- 柯里化函数的基础知识
- 实现部分函数的基础知识
- 以及更多
继续学习。
无需费力浏览视频或文档,即可练习 JavaScript 面试。Educative 的文本课程易于浏览,并配有实时编程环境,让学习快速高效。
《JavaScript 面试手册》:100+ 道面试题
关于 DOM 和 Web 浏览器的问题
什么是 DOM
为了测试你对 JavaScript 和 DOM 技能的了解,你可能会被问到这样的问题:
特征检测和特征推断有什么区别?
我们可以使用功能检测和功能推断来确定浏览器中是否存在某种 Web 技术。功能检测可以确定某个功能是否存在于特定浏览器中。功能推断则假设,如果某个功能在某个浏览器中可用,那么在其他浏览器中也同样可用。这个问题可能会在初级职位的面试中被问到。
你还可能会被问到关于属性 (attribute) 和特性 (property) 的问题。属性 (attribute)写在 HTML 文档中,其中的 HTML 标签可能具有属性 (attribute)。当该文档被覆盖到 DOM 对象模型时,属性 (attribute) 会转换为特性 (property)。
隐藏和显示
你还需要展示你实现 DOM 相关功能的能力,例如隐藏和显示文本。例如,你需要实现文本隐藏功能,点击按钮即可隐藏文本Hello World!
。请查看解决方案。
function hideShow() {
var ele = document.getElementById("hideDiv");
if (ele.style.display === "none") {
ele.style.display = "block";
} else {
ele.style.display = "none";
}
}
我们创建一个button
执行hideShow
函数的 ,以及一个div
包含文本的 。我们用它getElementById
来访问该div
元素。在第 3 行,我们检查style.display
属性是否为none
(也就是隐藏)。如果,我们将属性设置为 来true
显示元素。如果,我们将值设置为 来隐藏元素。display
block
false
display
none.
其他问题
还有许多其他 JavaScript 面试题可以测试你对 JavaScript 的 DOM 和 Web 浏览器技能的了解。其中包括:
- 要创建的 DOM 相关函数
getElementByAttribute
- 实现查询选择器以添加类
- 销毁并创建新按钮
- 实现与 DOM 相关的函数来判断某个元素是否是子元素
- 以及更多
如果您想了解有关 JavaScript 中 DOM 和 Web 浏览器技能的更多信息,请查看本指南进行介绍或复习。
其他问题
你还会看到一些与 JavaScript 安全性、事件处理和异步回调相关的问题。让我们来看看你需要了解的一些常见概念。
事件处理
- JavaScript 中的事件循环、事件队列和调用堆栈
- 调用堆栈和任务队列有什么区别?
- 事件冒泡和控制台输出
- 事件捕获和控制台输出
- 哪些方法可以防止事件冒泡?
- 以及更多
异步回调
- Async和await原理修改
func is not a function
出错的代码 - 实现
checkName
错误检查函数 Cannot read property ‘text’ of undefined
修改有错误的代码- 承诺、链接
.then
和.catch
语句的基础知识以顺序的方式打印数字 0-9,以便每个数字在随机等待时间后打印。 - 以及更多
安全
- 什么是同源策略?
- 理解/实现 JavaScript 中的 strict 关键字
- 修改代码以针对特定更改抛出错误
- 以及更多
资源
JavaScript 面试准备需要投入大量时间和精力,但最终是值得的!JavaScript 仍然是最受欢迎且薪资最高的编程语言之一。制定详细的计划,努力学习,并在遇到问题时提出问题。为了更好地帮助您做好未来的学习准备,我们整理了一份实用资源清单,以帮助您准备面试。
课程
-
JavaScript 面试手册:我们整理了 100 多个面试必知主题问题,旨在简化您的面试准备流程。本课程重点讲解面试官希望您掌握的 JavaScript 基础知识。通过实践和编程学习。
-
JavaScript 中的数据结构 - 可视化与练习:想要更多动手实践?本课程通过简单的可视化效果和测验,深入探讨数据结构问题的核心。
-
精通 JavaScript 面试:掌握数据结构技能后,是时候复习一下所有与 JavaScript 面试相关的知识了。本课程涵盖了所有内容。
文章
-
你必须知道的 7 个 JavaScript 数据结构:数据结构和算法是 JavaScript 面试的重要组成部分。在这里,你可以测试你对这些重要概念的编程技能。
-
JavaScript ES6 教程:刷新你的 JavaScript 技能并了解 ES6 及更高版本的所有新内容
-
5 种经过实践检验的编码面试准备技巧:向专家学习有关准备和执行编码面试的技巧
-
StackOverflow JavaScript 数据结构库:一个发现有用库(如 JSClass、Buckets 等)的绝佳资源
-
破解 JavaScript 面试的完美指南:根据您需要了解的最重要的概念,逐步指导您准备面试。