헤드라인 주요 제조업체의 전형적인 프론트엔드 인터뷰 질문 모음(답변 포함)

주요 제조업체의 전형적인 프론트엔드 인터뷰 질문 모음(답변 포함)

Feb 23, 2019 am 10:14 AM

주요 제조업체의 전형적인 프론트엔드 인터뷰 질문 모음(답변 포함)

[관련 추천: 프론트엔드 면접 질문(2020)]

1. React/Vue 프로젝트 작성 시 컴포넌트에 키를 작성해야 하는 이유와 그 기능은 무엇인가요?

키의 기능은 diff 알고리즘이 실행될 때 해당 노드를 더 빠르게 찾아 diff 속도를 향상시키는 것입니다.

vue와 React는 모두 diff 알고리즘을 사용하여 새 가상 노드와 이전 가상 노드를 비교하여 노드를 업데이트합니다. Vue의 diff 기능에서. 먼저 diff 알고리즘을 이해할 수 있습니다.

교차 비교 중에 새 노드와 이전 노드 간의 교차 비교 결과가 없으면 이전 노드 배열의 키를 새 노드의 키에 따라 비교하여 해당 이전 노드를 찾습니다(여기서는 키 => 인덱스 맵 매핑에 해당합니다). 찾을 수 없는 경우 새 노드로 간주됩니다. 키가 없으면 순회 검색 방법을 사용하여 해당 이전 노드를 찾습니다. 하나는 지도 매핑이고, 다른 하나는 순회 검색입니다. 비교하면. 지도 매핑이 더 빠릅니다.

vue 소스 코드 부분은 다음과 같습니다.

// vue 项目  src/core/vdom/patch.js  -488 行
// oldCh 是一个旧虚拟节点数组, 
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
       idxInOld = isDef(newStartVnode.key)
         ? oldKeyToIdx[newStartVnode.key]
         : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
로그인 후 복사

지도 기능 생성:

function createKeyToOldIdx (children, beginIdx, endIdx) {
 let i, key
 const map = {}
 for (i = beginIdx; i <= endIdx; ++i) {
   key = children[i].key
   if (isDef(key)) map[key] = i
 }
 return map
}
로그인 후 복사

탐색 및 찾기:

// sameVnode 是对比新旧节点是否相同的函数
function findIdxInOld (node, oldCh, start, end) {
   for (let i = start; i < end; i++) {
     const c = oldCh[i]

     if (isDef(c) && sameVnode(node, c)) return i
   }
 }
로그인 후 복사

2. 3'].map(parseInt)

처음 이 질문을 봤을 때 떠오른 답은 [1, 2, 3]이었는데 실제 답은 [1, NaN, NaN]이었습니다.

먼저 map 함수의 첫 번째 매개변수 콜백을 살펴보겠습니다.

var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Return element for new_array }[, thisArg])
로그인 후 복사

이 콜백은 총 3개의 매개변수를 받을 수 있으며, 첫 번째 매개변수는 현재 처리 중인 요소를 나타내고 두 번째 매개변수는 인덱스를 나타냅니다.

그리고parseInt는 문자열을 구문 분석하는 데 사용되어 문자열을 지정된 밑수를 가진 정수로 만듭니다.

parseInt(string, radix)는 두 개의 매개변수를 받습니다. 첫 번째 매개변수는 처리할 값(문자열)을 나타내고 두 번째 매개변수는 구문 분석 중 기수를 나타냅니다.

이 두 함수를 이해한 후 작업을 시뮬레이션할 수 있습니다.

parseInt('1', 0) // radix가 ​​0이고 문자열 매개변수가 "0x" 및 "0"으로 시작하지 않는 경우 다음을 따르세요. 10 기본 번호에 대해 처리되었습니다. 이때 1이 반환됩니다;

parseInt('2', 1) // 1진수(base 1)로 표현되는 숫자 중 최대값이 2보다 작아서 파싱할 수 없고 NaN이 반환됩니다.

parseInt('3', 2) // 2진수(바이너리)로 표현되는 숫자 중 최대값이 3보다 작아서 파싱할 수 없으며 NaN이 반환됩니다.

map 함수는 배열을 반환하므로 최종 결과는 [1, NaN, NaN]입니다.

3. 흔들림 방지 및 스로틀링이란 무엇인가요? 차이점은 무엇입니까? 달성하는 방법?

1) 흔들림 방지

이 기능은 고주파 이벤트가 발생한 후 n초 이내에 한 번만 실행됩니다. n초 내에 고주파 이벤트가 다시 발생하면 시간이 다시 계산됩니다. ;

아이디어:

매번 이벤트가 발생하면 이전 지연 호출 방법이 취소됩니다.

function debounce(fn) {
     let timeout = null; // 创建一个标记用来存放定时器的返回值
     return function () {
       clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
       timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
         fn.apply(this, arguments);
       }, 500);
     };
   }
   function sayHi() {
     console.log(&#39;防抖成功&#39;);
   }

   var inp = document.getElementById(&#39;inp&#39;);
   inp.addEventListener(&#39;input&#39;, debounce(sayHi)); // 防抖
로그인 후 복사

2) Throttling

고빈도 이벤트가 발생하지만 n초에 한 번만 실행됩니다. , 따라서 조절은 함수의 실행 빈도를 희석시킵니다.

아이디어:

이벤트가 발생할 때마다 실행을 기다리는 지연 기능이 있는지 판단합니다.

function throttle(fn) {
     let canRun = true; // 通过闭包保存一个标记
     return function () {
       if (!canRun) return; // 在函数开头判断标记是否为 true,不为 true 则 return
       canRun = false; // 立即设置为 false
       setTimeout(() => { // 将外部传入的函数的执行放在 setTimeout 中
         fn.apply(this, arguments);
         // 最后在 setTimeout 执行完毕后再把标记设置为 true(关键) 表示可以执行下一次循环了。当定时器没有执行的时候标记永远是 false,在开头被 return 掉
         canRun = true;
       }, 500);
     };
   }
   function sayHi(e) {
     console.log(e.target.innerWidth, e.target.innerHeight);
   }
   window.addEventListener(&#39;resize&#39;, throttle(sayHi));
로그인 후 복사

4. Set, Map, WeakSet 및 WeakMap의 차이점을 소개하세요.

1) Set

멤버는 고유하고 순서가 없으며 반복되지 않습니다.

[값, 값], 키 값과 키 이름이 일치합니다(또는 키 값만, 키 이름 없음).

순회할 수 있으며 메소드는 추가, 삭제, 보유입니다.

2) WeakSet

멤버는 모두 객체입니다.

멤버는 모두 약한 참조이고 가비지 수집 메커니즘으로 재활용할 수 있으며 DOM 노드를 저장하는 데 사용할 수 있으며 메모리 누수가 발생하지 않습니다. 순회되며 메소드는 add,delete,has입니다.

3) Map

은 본질적으로 컬렉션과 유사한 키-값 쌍의 컬렉션입니다.

탐색할 수 있고 다양한 메서드가 있으며 다양한 데이터 형식으로 변환할 수 있습니다.

4) WeakMap

은 객체만 키 이름(null 제외)으로 허용하고 다른 유형의 값을 키 이름으로 허용하지 않습니다.

키 이름은 약한 참조이며 키 값은 무엇이든 가능합니다. , 키 이름으로 가리키는 개체 가비지 수집될 수 있으며 현재 키 이름은 유효하지 않습니다.

탐색할 수 없으며 메서드에는 get, set, has 및 delete가 포함됩니다.

5. 깊이 우선 순회와 너비 우선 순회를 도입하고 이를 구현하는 방법은 무엇인가요?

DFS(깊이 우선 순회)

깊이 우선 검색은 트리의 깊이를 따라 트리의 노드를 순회하여 가능한 한 깊이까지 트리를 검색하는 검색 알고리즘입니다. 노드 v의 모든 모서리를 탐색한 후 노드 v가 발견된 모서리의 시작 노드로 역추적을 수행합니다. 이 과정은 소스 노드가 다른 모든 노드에 대해 탐색될 때까지 계속됩니다. 아직 탐색되지 않은 노드가 있는 경우 탐색되지 않은 노드 중 하나를 소스 노드로 선택하고 모든 노드가 탐색될 때까지 위의 작업을 반복합니다.

简单的说,DFS 就是从图中的一个节点开始追溯,直到最后一个节点,然后回溯,继续追溯下一条路径,直到到达所有的节点,如此往复,直到没有路径为止。

DFS 可以产生相应图的拓扑排序表,利用拓扑排序表可以解决很多问题,例如最大路径问题。一般用堆数据结构来辅助实现 DFS 算法。

注意:深度 DFS 属于盲目搜索,无法保证搜索到的路径为最短路径,也不是在搜索特定的路径,而是通过搜索来查看图中有哪些路径可以选择。

步骤:

访问顶点 v;

依次从 v 的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和 v 有路径相通的顶点都被访问;

若此时途中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到所有顶点均被访问过为止。

实现:

Graph.prototype.dfs = function() {
   var marked = []
   for (var i=0; i<this.vertices.length; i++) {
       if (!marked[this.vertices[i]]) {
           dfsVisit(this.vertices[i])
       }
   }

   function dfsVisit(u) {
       let edges = this.edges
       marked[u] = true
       console.log(u)
       var neighbors = edges.get(u)
       for (var i=0; i<neighbors.length; i++) {
           var w = neighbors[i]
           if (!marked[w]) {
               dfsVisit(w)
           }
       }
   }
}
로그인 후 복사

测试:

graph.dfs()
// 1
// 4
// 3
// 2
// 5
로그인 후 복사

测试成功。

广度优先遍历(BFS)

广度优先遍历(Breadth-First-Search)是从根节点开始,沿着图的宽度遍历节点,如果所有节点均被访问过,则算法终止,BFS 同样属于盲目搜索,一般用队列数据结构来辅助实现 BFS。

BFS 从一个节点开始,尝试访问尽可能靠近它的目标节点。本质上这种遍历在图上是逐层移动的,首先检查最靠近第一个节点的层,再逐渐向下移动到离起始节点最远的层。

步骤:

创建一个队列,并将开始节点放入队列中;

若队列非空,则从队列中取出第一个节点,并检测它是否为目标节点;

若是目标节点,则结束搜寻,并返回结果;

若不是,则将它所有没有被检测过的字节点都加入队列中;

若队列为空,表示图中并没有目标节点,则结束遍历。

实现:

Graph.prototype.bfs = function(v) {
   var queue = [], marked = []
   marked[v] = true
   queue.push(v) // 添加到队尾
   while(queue.length > 0) {
       var s = queue.shift() // 从队首移除
       if (this.edges.has(s)) {
           console.log(&#39;visited vertex: &#39;, s)
       }
       let neighbors = this.edges.get(s)
       for(let i=0;i<neighbors.length;i++) {
           var w = neighbors[i]
           if (!marked[w]) {
               marked[w] = true
               queue.push(w)
           }
       }
   }
}
로그인 후 복사

测试:

graph.bfs(1)
// visited vertex:  1
// visited vertex:  4
// visited vertex:  3
// visited vertex:  2
// visited vertex:  5
로그인 후 복사

测试成功。

6. 异步笔试题

请写出下面代码的运行结果:

// 今日头条面试题
async function async1() {
   console.log(&#39;async1 start&#39;)
   await async2()
   console.log(&#39;async1 end&#39;)
}
async function async2() {
   console.log(&#39;async2&#39;)
}
console.log(&#39;script start&#39;)
setTimeout(function () {
   console.log(&#39;settimeout&#39;)
})
async1()
new Promise(function (resolve) {
   console.log(&#39;promise1&#39;)
   resolve()
}).then(function () {
   console.log(&#39;promise2&#39;)
})
console.log(&#39;script end&#39;)
로그인 후 복사

题目的本质,就是考察setTimeout、promise、async await的实现及执行顺序,以及 JS 的事件循环的相关问题。

答案:

script start
async1 start
async2
promise1
script end
async1 end
promise2
settimeout
로그인 후 복사

7. 将数组扁平化并去除其中重复数据,最终得到一个升序且不重复的数组

Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})
로그인 후 복사

8.JS 异步解决方案的发展历程以及优缺点。

1)回调函数(callback)

setTimeout(() => {
   // callback 函数体
}, 1000)
로그인 후 복사

缺点:回调地狱,不能用 try catch 捕获错误,不能 return

回调地狱的根本问题在于:

缺乏顺序性: 回调地狱导致的调试困难,和大脑的思维方式不符;

嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身,即(控制反转);

嵌套函数过多的多话,很难处理错误。

ajax(&#39;XXX1&#39;, () => {
   // callback 函数体
   ajax(&#39;XXX2&#39;, () => {
       // callback 函数体
       ajax(&#39;XXX3&#39;, () => {
           // callback 函数体
       })
   })
})
로그인 후 복사

优点:解决了同步的问题(只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行)。

2)Promise

Promise 就是为了解决 callback 的问题而产生的。

Promise 实现了链式调用,也就是说每次 then 后返回的都是一个全新 Promise,如果我们在 then 中 return ,return 的结果会被 Promise.resolve() 包装。

优点:解决了回调地狱的问题。

ajax(&#39;XXX1&#39;)
 .then(res => {
     // 操作逻辑
     return ajax(&#39;XXX2&#39;)
 }).then(res => {
     // 操作逻辑
     return ajax(&#39;XXX3&#39;)
 }).then(res => {
     // 操作逻辑
 })
로그인 후 복사

缺点:无法取消 Promise ,错误需要通过回调函数来捕获。

3)Generator

特点:可以控制函数的执行,可以配合 co 函数库使用。

function *fetch() {
   yield ajax(&#39;XXX1&#39;, () => {})
   yield ajax(&#39;XXX2&#39;, () => {})
   yield ajax(&#39;XXX3&#39;, () => {})
}
let it = fetch()
let result1 = it.next()
let result2 = it.next()
let result3 = it.next()
로그인 후 복사

4)Async/await

async、await 是异步的终极解决方案。

优点是:代码清晰,不用像 Promise 写一大堆 then 链,处理了回调地狱的问题;

缺点:await 将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用 await 会导致性能上的降低。

async function test() {
 // 以下代码没有依赖性的话,完全可以使用 Promise.all 的方式
 // 如果有依赖性的话,其实就是解决回调地狱的例子了
 await fetch(&#39;XXX1&#39;)
 await fetch(&#39;XXX2&#39;)
 await fetch(&#39;XXX3&#39;)
}
로그인 후 복사

下面来看一个使用 await 的例子:

let a = 0
let b = async () => {
 a = a + await 10
 console.log(&#39;2&#39;, a) // -> &#39;2&#39; 10
}
b()
a++
console.log(&#39;1&#39;, a) // -> &#39;1&#39; 1
로그인 후 복사

对于以上代码你可能会有疑惑,让我来解释下原因:

首先函数 b 先执行,在执行到 await 10 之前变量 a 还是 0,因为 await 内部实现了 generator ,generator 会保留堆栈中东西,所以这时候 a = 0 被保存了下来;

因为 await 是异步操作,后来的表达式不返回 Promise 的话,就会包装成 Promise.reslove(返回值),然后会去执行函数外的同步代码;

同步代码执行完毕后开始执行异步代码,将保存下来的值拿出来使用,这时候 a = 0 + 10。

await가 내부적으로 생성기를 구현한다고 언급한 위의 설명은 실제로 wait는 생성기의 구문 설탕에 Promise를 더한 것이며 내부적으로 생성기의 자동 실행을 구현합니다. co에 익숙하다면 실제로 이러한 구문 설탕을 직접 구현할 수 있습니다.

9. TCP 3방향 핸드셰이크와 4방향 웨이브에 대한 이해에 대해 이야기해 주세요.

주요 제조업체의 전형적인 프론트엔드 인터뷰 질문 모음(답변 포함)

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)