골든 쓰리 실버 포시즌, 최근 몇 년간 프론트엔드가 핫한 분야인데, 특히 분위기가 강한 친구 샤오웨이가 최근 미친 듯이 인터뷰를 진행하며 흥미로운 면접관과 흥미로운 인터뷰 질문을 많이 만났습니다. 내가 도와줘요 이 말썽꾸러기 소년의 말을 바꿔보겠습니다.
다음은 내 친구의 이야기입니다. 실제로는 제가 아닙니다.
for (var i = 0; i < 5; i++) { console.log(i); }
"Xiaowei, 이 코드 줄이 무엇을 출력할지 말해주세요."
면접관이 Sublime에서 이 코드 줄을 입력했을 때 저는 약간 혼란스러웠습니다. 대합? 이것이 가장 간단한 루프가 아닌가? 함정이 있는 걸까요? 제가 본 종결 질문과 매우 유사한 것 같습니다. 그것은 유독하다.
"0부터 4까지 직접 출력해야지..."라고 힘없이 말했다.
"네, 긴장하지 마세요. 이 질문에는 함정이 없습니다. 그냥 아무렇지도 않게 씁니다."
(실례합니다. 면접관님, 웃기려고 오신 건가요? 겁나 무서워! )
"그럼 이 코드 줄의 출력을 보고 있는 겁니까?"
으으으음, 도대체 왜 종결 질문이 아닌가요? 그렇게 많이 외웠나? setTimeout은 실행을 지연시키므로 console.log가 실행되면 실제로 5가 됩니다. 예, 그게 다입니다. 그렇게 간단한 일을 하는 것이 어떻게 그렇게 어려울 수 있습니까? <…
드디어 익숙한 내용인데 클로저만 추가하면 해결되고 안정적이네요!
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000 * i);}
“좋습니다. 이 i를 삭제하면 어떻게 되는지 알려주실 수 있나요?”
for (var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { console.log(i); }, i * 1000); })(i); }
“이 경우 i에 대한 내부 참조가 없습니다. 출력 5가 됩니다. "
"아주 좋아요. 바꿔서 결과가 어떻게 나올지 볼까요?"
for (var i = 0; i < 5; i++) { (function() { setTimeout(function() { console.log(i); }, i * 1000); })(i); }
조개? 도대체 무슨 일이 일어나고 있는 걸까요, 생각해 보도록 하겠습니다. 여기서는 즉시 실행 함수가 setTimeout에 전달됩니다. 음, setTimeout은 함수나 문자열을 매개변수로 받아들일 수 있는데 여기서 즉시 실행 함수는 무엇입니까? 정의되지 않아야 하며 이는 다음과 같습니다.
for (var i = 0; i < 5; i++) { setTimeout((function(i) { console.log(i); })(i), i * 1000); }
그리고 즉시 실행 함수는 즉시 실행되므로 다음과 같습니다. 즉시 출력합니다.
"즉시 0부터 4까지 출력해야지."
"아, 나쁘지 않은데, 마지막 질문, Promise를 아시나요?"
"괜찮아... "
"좋아, 그럼 이 질문을 해봐."
아아아WTF! ! ! ! 나는 조용히하고 싶다!
이 질문은 내 JavaScript의 실행 메커니즘을 조사해야 합니다.
처음에는 setTimeout이 발생하므로 타이머가 먼저 설정되고 타이머가 끝난 후 함수가 작업 대기열로 전달되므로 처음에는 1이 출력되지 않습니다.
그리고 Promise가 있는데, 내부의 함수가 직접 실행되므로 2 3을 직접 출력해야 합니다.
그런 다음 Promise의 then은 현재 틱의 끝에 배치되어야 하지만 여전히 현재 틱에 있어야 합니다.
따라서 5가 먼저 출력되고 그 다음에 4가 출력되어야 합니다.
마지막으로 다음 틱은 1 입니다.
“2 3 5 4 1”
“자, 다음 면접을 기다리자.”
참 쉽죠! 엄마는 더 이상 내 인터뷰에 대해 걱정하지 않아도 됩니다.