function foo(a) {
if (/* Some condition */) {
// perform task 1
// perform task 3
}
else {
// perform task 2
// perform task 3
}
}
위와 비슷한 구조의 기능이 있습니다. 작업 3 을 함수로 추상화하고 싶지만 bar()
이 함수의 액세스를 범위 내로 만 제한하고 싶습니다 foo(a)
.
내가 원하는 것을 달성하기 위해 다음으로 변경하는 것이 옳습니까?
function foo(a) {
function bar() {
// Perform task 3
}
if (/* Some condition */) {
// Perform task 1
bar();
}
else {
// Perform task 2
bar();
}
}
위의 내용이 맞으면 호출 bar()
될 때마다 get 재정의 foo(a)
됩니까? (여기서 CPU 리소스 낭비가 걱정됩니다.)
답변
네, 당신이 가지고있는 것이 옳습니다. 몇 가지 참고 사항 :
bar
함수를 호출 할 때마다 생성foo
되지만 다음과 같습니다.- 최신 브라우저에서 이것은 매우 빠른 프로세스입니다. (일부 엔진은 코드 를 한 번만 컴파일 한 다음 매번 다른 컨텍스트로 해당 코드를 재사용 할 수 있습니다. 대부분의 경우 Google의 V8 엔진 (Chrome 및 기타)에서 수행합니다.)
- 그리고 무엇을하는지에 따라
bar
일부 엔진은이를 “인라인”하여 함수 호출을 완전히 제거 할 수 있다고 결정할 수 있습니다. V8이이 작업을 수행하며, 이것이 수행하는 유일한 엔진은 아닙니다. 당연히 코드의 동작을 변경하지 않는 경우에만이를 수행 할 수 있습니다.
bar
매번 생성 되는 성능 영향 은 JavaScript 엔진마다 크게 다릅니다.bar
사소한 경우 감지 할 수없는 것부터 매우 작은 것까지 다양합니다.foo
(예를 들어mousemove
핸들러에서) 연속으로 수천 번 호출 하지 않는다면 걱정하지 않을 것입니다. 당신이 그렇더라도 느린 엔진에서 문제를 본 경우에만 걱정할 것입니다. 다음은 DOM 작업과 관련된 테스트 케이스 입니다. 이는 영향이 있음을 시사하지만 사소한 것입니다 (아마도 DOM에 의해 씻겨 나옴). 여기에 순수 계산하고 테스트 케이스의 어떤 쇼 훨씬 더 높은 영향을하지만, 솔직히 심지어 우리의 차이를 얘기 마이크로 무언가에 심지어 92 % 증가합니다 그 때문에 초 미세발생하는 시간은 여전히 매우, 매우 빠릅니다. 실제 영향을보기 전까지는 걱정할 필요가 없습니다.bar
함수 내에서만 액세스 할 수 있으며 해당 함수 호출에 대한 모든 변수 및 인수에 액세스 할 수 있습니다. 이것은 매우 편리한 패턴을 만듭니다.- 함수 선언을 사용했기 때문에 선언 위치 (위쪽, 아래쪽 또는 중간)는 흐름 제어 문 내부가 아니라 함수의 최상위 수준에있는 한 중요하지 않습니다. 구문 오류), 단계별 코드의 첫 번째 줄이 실행되기 전에 정의됩니다.
답변
이것이 클로저의 목적입니다.
var foo = (function () {
function bar() {
// perform task 3
};
function innerfoo (a) {
if (/* some cond */ ) {
// perform task 1
bar();
}
else {
// perform task 2
bar();
}
}
return innerfoo;
})();
Innerfoo (클로저)는 bar에 대한 참조를 보유하며, 클로저를 생성하기 위해 한 번만 호출되는 익명 함수에서 innerfoo에 대한 참조 만 반환됩니다.
바는 외부에서이 방법으로 접근 할 수 없습니다.
답변
var foo = (function () {
var bar = function () {
// perform task 3
}
return function (a) {
if (/*some condition*/) {
// perform task 1
bar();
}
else {
// perform task 2
bar();
}
};
}());
클로저는 bar()
포함 된 범위를 유지하고 자체 실행 익명 함수에서 새 함수를 반환하면보다 가시적 인 범위를 foo()
. 익명의 자체 실행 기능은 정확히 한 번만 실행되므로 bar()
인스턴스 가 하나 뿐이며 모든 실행이 foo()
이를 사용합니다.
답변
예, 잘 작동합니다.
내부 기능은 외부 기능을 입력 할 때마다 다시 생성되지 않지만 다시 할당됩니다.
이 코드를 테스트하는 경우 :
function test() {
function demo() { alert('1'); }
demo();
demo = function() { alert('2'); };
demo();
}
test();
test();
이 표시됩니다 1
, 2
, 1
, 2
,하지 1
, 2
, 2
, 2
.
답변
중첩 및 비 중첩 및 함수 표현식과 함수 선언을 테스트하기 위해 jsperf를 만들었는데 중첩 테스트 케이스가 비 중첩보다 20 배 더 빠르게 수행된다는 사실에 놀랐습니다. (나는 그 반대 또는 무시할만한 차이를 예상했습니다).
https://jsperf.com/nested-functions-vs-not-nested-2/1
이것은 Chrome 76, macOS에 있습니다.