30 个最佳 JavaScript 面试热身练习(第 2 部分)

2025-05-27

30 个最佳 JavaScript 面试热身练习(第 2 部分)

阅读 CodeThat.today 上的原文

欢迎回来。这是 30 个 JavaScript 面试热身练习系列的第二部分。如果你要参加一场涉及 JavaScript 算法问题的面试,那么应该把这份练习列表收藏起来,以便参考。

让我们开始吧。

问题🤔

  • 1. 编写一个函数,接受一个数字并检查它是否是素数。

要检查一个数是否为质数,我们需要遍历从 2 到 的n数字列表,并检查是否能整除这个数。这是为了确保不能用 的因数来表示in/2nini

代码要点如下:

function isPrime(n) { if (n === 1) { // Special case for 1 return false; } else { // Go through all numbers from 2 up until n/2 for (let i = 2; i <= n / 2; i += 1) { if (n % i === 0) { // We found a number i such as i * x = n so the number is not prime return false; } } // If we got to this point then we know the number is prime return true; } } let num = 45; console.info("Is " + num + " a prime?: " + isPrime(num)); num = 37; console.info("Is " + num + " a prime?: " + isPrime(num)); num = 73; console.info("Is " + num + " a prime?: " + isPrime(num));
  • 2. 编写一个函数,接受具有以下类型结构的对象列表:
{
   id: number,
   accountType: "user" | "admin" | "root"
   name: string
}

Enter fullscreen mode Exit fullscreen mode

该函数应返回按以下顺序分组的对象列表accountType。例如,它应返回一个列表,其中包含用户列表、管理员列表和root帐户列表。

为了按帐户类型分组,我们需要以这样的方式存储它们:键是accountType值(用户、管理员或根),值是包含该值的记录列表accountType。我们可以使用 map,只需遍历这些键,并在每次匹配到值时更新集合。

accountType然后,为了按自定义顺序返回结果,我们只需将数组中每种类型的结果组合起来。

代码要点如下:

// Somewhat generic group function function groupBy(records, keyFunc) { // Save groups by key here. const groups = new Map(); for (record of records) { // We need this call to retrieve the actual key const key = keyFunc(record); if (groups.has(key)) { const data = groups.get(key); data.push(record); } else { groups.set(key, [record]); } } return groups; } function getGroupsByAccountType (records) { const groups = groupBy(records,function(record) { return record.accountType; }); // Return by custom ordering here return [ ...groups.get('user'), ...groups.get('admin'), ...groups.get('root'), ] } console.info(getGroupsByAccountType([ { id: 1, accountType: 'user', name: 'Mike' }, { id: 2, accountType: 'admin', name: 'Alex' }, { id: 3, accountType: 'root', name: 'Jordan' }, { id: 4, accountType: 'user', name: 'Silas' }, { id: 5, accountType: 'admin', name: 'John' }, ]))
  • 3. 编写一个函数,接受一个 DOM 元素和一个字符串,并打印其任何包含该字符串的类名的直接子元素。

使用 DOM API,我们可以通过childNodes属性请求当前元素子元素的 NodeList 。然后,我们可以迭代此列表,并class使用getAttribute("class")classList属性检查指定类名的值。

代码要点如下:

例如,给出以下 DOM:

<ul id="list">
    <li class="even"><a href="#Syntax" rel="internal">Syntax</a></li>
    <li class="odd"><a href="#Examples" rel="internal">Examples</a></li>
    <li class="even"><a href="#Polyfill" rel="internal">Polyfill</a></li>
    <li class="odd"><a href="#Specifications" rel="internal">Specifications</a></li>
    <li class="even"><a href="#Browser_compatibility" rel="internal">Browser compatibility</a></li>
    <li class="even"><a href="#See_also" rel="internal">See also</a></li>
</ul>
Enter fullscreen mode Exit fullscreen mode

打印具有目标 className 的子节点的代码是:

function printChildrenContainingClass(rootElement, className) {
  if (rootElement) {
    // Iterate over the childNodes
    list.childNodes.forEach((node) => {
      // If a childnode contains a className print the node
      if (node.classList.contains(className)) {
        console.info(node);
      }
    });
  }
}

printChildrenContainingClass(document.querySelector('#list'), 'odd'));
Enter fullscreen mode Exit fullscreen mode
  • 4. 编写一个函数,接受一个 DOM 元素和一个字符串作为参数,并打印该元素的父节点中是否有包含该字符串的类。当没有父元素时,该函数应该停止。

这里我们可以使用parentNode属性来获取当前元素的父节点。然后检查父节点是否包含同名的类。如果没有,我们将再次递归获取该节点的父节点,直到到达文档节点或没有父节点的节点:

代码要点如下:

例如,给出以下 DOM:

<body>
    <aside class="sidebar">
        <ul id="list" class="sidebar-list">
            <li class="even"><a href="#Syntax" rel="internal">Syntax</a></li>
            <li class="odd"><a href="#Examples" rel="internal">Examples</a></li>
            <li class="even"><a href="#Polyfill" rel="internal">Polyfill</a></li>
            <li class="odd"><a href="#Specifications" rel="internal">Specifications</a></li>
            <li class="even"><a id="start" href="#Browser_compatibility" rel="internal">Browser compatibility</a></li>
            <li class="even"><a href="#See_also" rel="internal">See also</a></li>
        </ul>
    </aside>
</body>
Enter fullscreen mode Exit fullscreen mode

打印具有目标 className 的父节点的代码是:


function printParentsContainingClass(childElement, className) {
  if (childElement) {
    // Iterate over the parentNodes
    let parentNode = childElement.parentNode;
    while (parentNode !== null) {
      // If a parentNode contains a className print the node
      if (parentNode.classList && parentNode.classList.contains(className)) {
        console.info(parentNode);
      }
      // Go up
      parentNode = parentNode.parentNode;
    }
  }
}

printParentsContainingClass(document.getElementById('start'), 'sidebar');

Enter fullscreen mode Exit fullscreen mode
  • 5. 给定以下 DOM 结构:
<ul id="list-start">
   <li>Theo</li>
   <li>Alex</li>
   <li>Mike</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

编写相关的 Javascript 代码,以便当我们单击任何列表元素时,浏览器中将显示以下警报:

<name> was clicked元素被点击的位置在哪里<name>?如何让它只使用一个事件监听器?

我们可以在这里为每个元素添加一个单独的事件监听器,<li>但更好的方法是在父节点中使用一个<ul>。这样做的目的是利用事件传播和冒泡,这样当我们点击<ul>区域内的任意位置时,我们就会选择当前目标文本节点并显示警报消息。

代码要点如下:

function onListElementClicked(event) {
  if(event.target && event.target.nodeName == "LI") {
    // List item found. Alert the innerText
    alert(event.target.innerText +  " was clicked");
  }
}

let list = document.getElementById('list-start');
if (list) {
  list.addEventListener('click', onListElementClicked);
}
Enter fullscreen mode Exit fullscreen mode
  • 6. 编写一个函数检查给定的字符串是否是回文。

根据定义,如果一个字符串倒着读,其内容相同,则该字符串为回文。例如,以下字符串就是回文:

“aba”、“assissa”

但是以下字符串不是回文:

“abc”、“阿西比萨”

我们可以使用 for 循环遍历两个索引来检查字符串是否为回文。第一个索引从字符串的开头开始,第二个索引从结尾开始并向开头移动。如果在任意时刻,S[i] !== S[j] 处的字符不匹配,则说明该字符串不是回文。循环到字符串中间时停止。

代码要点如下:

function isPalindrome(inputStr) { let lo = 0; let hi = inputStr.length; let mid = Math.floor((lo + hi) / 2); // Check until the mid element for (let i = 0, j = hi-1; i < mid; i += 1, j -= 1) { if (inputStr[i] !== inputStr[j]) { return false; } } // If we got in here then we know that the string is palindrome return true; } console.info(isPalindrome("ab")) console.info(isPalindrome("a")) console.info(isPalindrome("aba")) console.info(isPalindrome("abc")) console.info(isPalindrome("abba"))
  • 7. 编写一个函数来表示一个链表。

很多时候,你会被要求在链表中实现一些操作,比如反转列表或查找循环。因此,能够快速实现这些操作非常重要。以下是一个简单的实现,包含一些基本操作:

// Node holds the data and a reference to the next node function LinkListNode(data) { this.data = data; this.next = null; } // Linked list Basic Structure function LinkedList() { this.len = 0; this.head = null; } // Operations LinkedList.prototype.push = function(item) { if (item) { let node = new LinkListNode(item); // if the current head is null we set item as head and update the length if (!this.head) { this.head = node; this.len += 1; return node; } // Otherwise we follow the next links until we reach the end of the list let currentNode = this.head; while (currentNode.next !== null) { currentNode = currentNode.next; } // If we got here then we have reached the end. currentNode points to the last element currentNode.next = node; this.len += 1; return node; } }; LinkedList.prototype.head = function() { return this.head; }; LinkedList.prototype.length = function() { return this.len; }; let list = new LinkedList(); list.push(1); list.push(2); list.push(3); list.push(4); console.info('List is: '); let currentNode = list.head while(currentNode !== null) { console.info(currentNode.data); currentNode = currentNode.next; }
  • 8. 编写一个函数来表示一个堆栈。

很多时候,你会被要求实现一个使用栈的算法,比如深度优先遍历或检查表达式是否平衡。因此,能够快速实现栈非常重要。以下是一个简单的实现,包含几个基本操作:

function Stack() { this.items = []; } // Operations Stack.prototype.push = function(item) { this.items.push(item); } Stack.prototype.pop = function() { return this.items.pop(); } Stack.prototype.top = function() { return this.items[this.items.length - 1]; } Stack.prototype.isEmpty = function() { return this.items.length === 0; } let stack = new Stack(); stack.push(1); stack.push(2); stack.push(3); stack.push(4); console.info('Stack is: ', ); while(!stack.isEmpty()) { console.info(stack.pop()); }
  • 9. 编写表示队列数据结构的代码。

很多时候,你会被要求实现一个使用队列的算法,比如BFS遍历。因此,能够实时实现这个算法非常重要。以下是一个简单的实现,包含一些基本操作:

function Queue() { this.items = []; } Queue.prototype.enqueue = function(item) { this.items.push(item); } Queue.prototype.dequeue = function() { return this.items.shift(); } Queue.prototype.top = function() { if (this.items.length > 0) { return this.items[0]; } return null; } Queue.prototype.isEmpty = function() { return this.items.length === 0; } let q = new Queue(); q.enqueue(1); q.enqueue(2); q.enqueue(3); q.enqueue(4); console.info('Queue is: ', ); while(!q.isEmpty()) { console.info(q.dequeue()); }
  • 10. 编写表示图形数据结构的代码。

很多时候,你会被要求实现一个使用图 DTS 的算法,比如查找最短路径。因此,能够实时实现这个算法非常重要。以下是一个简单的实现,包含一些基本操作:

function Graph() { this.vertices = new Map(); this.edges = []; } Graph.prototype.addVertex = function(vertex) { this.vertices.set(vertex, vertex); this.edges[vertex] = []; }; Graph.prototype.addEdge = function(from, to) { this.edges[from].push(to); this.edges[to].push(from); }; Graph.prototype.size = function() { return this.vertices.size; }; Graph.prototype.removeVertex = function(vertex) { // Check if vertex exists if (this.vertices.has(vertex)) { this.vertices.delete(vertex); // Find all relevant edges and delete them while (this.edges[vertex].length > 0) { let linkedVertex = this.edges[vertex].pop(); // Remove all edges pointing to this vertex. this.removeEdge(linkedVertex, vertex); } } }; Graph.prototype.removeEdge = function(from, to) { // Find all references of from edges and remove them let firstIndex = this.edges[from] ? this.edges[from].indexOf(to) : -1; // Find all references of to edges and remove them let secondIndex = this.edges[to] ? this.edges[to].indexOf(from) : -1; if (firstIndex !== -1) { this.edges[from].splice(firstIndex, 1); } if (secondIndex !== -1) { this.edges[to].splice(secondIndex, 1); } }; let graph = new Graph(); graph.addVertex(1); graph.addVertex(2); graph.addVertex(3); graph.addVertex(4); graph.addEdge(1, 2); graph.addEdge(1, 3); graph.addEdge(2, 3); graph.addEdge(2, 4); graph.addEdge(3, 4); graph.removeVertex(2); console.info(graph);

下一步

请继续关注下一部分!

😉👌💖

对指导或培训感兴趣吗?

请通过www.techway.io与我联系以获取更多信息。

文章来源:https://dev.to/theodesp/top-30-javascript-interview-warmup-exercises-part-2-58i1
PREV
热门 CSS 面试问题及详细解答✌️🤩✌️ 第一部分
NEXT
30 个最佳 JavaScript 面试热身练习