JavaScript 함수 순서 : 왜 중요한가요?


106

원래 질문 :

JSHint는 내 JavaScript가 호출보다 페이지 아래에 더 정의 된 함수를 호출 할 때 불평합니다. 그러나 내 페이지는 게임용이며 전체 다운로드가 완료 될 때까지 함수가 호출되지 않습니다. 그렇다면 주문 함수가 내 코드에 나타나는 이유는 무엇입니까?

편집 : 답을 찾은 것 같습니다.

http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

나는 안에서 신음하고있다. 6 천 줄의 코드를 다시 주문하는 데 다른 하루를 보내야하는 것 같습니다. 자바 스크립트의 학습 곡선은 전혀 가파르지는 않지만 매우 길다.


업데이트에서 훌륭한 참조를 위해 +1. 코드를 다시 정렬 할 필요가 없다는 사실을 확신 할 수 있기를 바랍니다. :)
awm 2011 년

답변:


294

tl; dr 모든 것이로드 될 때까지 아무것도 호출하지 않으면 괜찮습니다.


편집 : 일부 ES6 선언 ( let, const)을 다루는 개요 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Scope_Cheatsheet

이 이상한 행동은

  1. 기능을 정의하는 방법 및
  2. 당신이 그들을 부를 때.

다음은 몇 가지 예입니다.

bar(); //This won't throw an error
function bar() {}

foo(); //This will throw an error
var foo = function() {}
bar();
function bar() {
    foo(); //This will throw an error
}
var foo = function() {}
bar();
function bar() {
    foo(); //This _won't_ throw an error
}
function foo() {}
function bar() {
    foo(); //no error
}
var foo = function() {}
bar();

이것은 호이 스팅 이라고 불리는 것 때문입니다 !

함수를 정의하는 방법에는 함수 선언 과 함수 표현식의 두 가지가 있습니다 . 차이점은 성가신, 분, 그래서 그냥이 약간 잘못된 말을하자 : 당신처럼 작성하는 경우 function name() {}, 그것은의 선언 , 그리고 당신처럼 쓸 때 var name = function() {}(또는 반환에 할당 된 익명 함수, 그런 일이), 그것의 함수 표현식 .

먼저 변수가 처리되는 방법을 살펴 보겠습니다.

var foo = 42;

//the interpreter turns it into this:
var foo;
foo = 42;

이제 함수 선언 이 처리되는 방법 :

var foo = 42;
function bar() {}

//turns into
var foo; //Insanity! It's now at the top
function bar() {}
foo = 42;

var진술은 생성foo맨 위에 "던져" 지만 아직 가치를 할당하지는 않습니다. 함수 선언이 다음 줄에 나오고 마지막으로 값이에 할당됩니다 foo.

그리고 이것은 어떻습니까?

bar();
var foo = 42;
function bar() {}
//=>
var foo;
function bar() {}
bar();
foo = 42;

선언foo상단으로 이동합니다. 할당은 bar모든 호이 스팅이 발생하기 전인 호출 이 이루어진 후에 만 이루어집니다.

그리고 마지막으로 간결함을 위해 :

bar();
function bar() {}
//turns to
function bar() {}
bar();

이제 함수 표현식은 어떻습니까?

var foo = function() {}
foo();
//=>
var foo;
foo = function() {}
foo();

그냥 일반 변수처럼, 처음 foo됩니다 선언 다음에 값이 할당되고, 범위의 가장 높은 지점에서.

두 번째 예제에서 오류가 발생하는 이유를 살펴 보겠습니다.

bar();
function bar() {
    foo();
}
var foo = function() {}
//=>
var foo;
function bar() {
    foo();
}
bar();
foo = function() {}

이전에 보았던 것처럼 생성 만 foo게양되고 할당은 "원본"(게재되지 않은) 코드에 나타난 위치에 제공됩니다. bar를 호출 하면 이전 foo에 값이 할당되므로 foo === undefined. 이제의 함수 본문에서 bar마치 수행하는 것처럼 undefined()오류가 발생합니다.


이것을 파헤쳐 서 미안하지만 Array.prototype.someMethod = function () {}과 같은 과부하가 발생합니까? 이러한 유형의 항목이 스크립트 끝에 있으면 오류가 발생하는 것 같습니다.
에지

모든 것이로드 되는지 어떻게 확인 합니까? 일반적인 관행이 있습니까?
zwcloud

6

주된 이유는 아마도 JSLint가 파일에 대해 하나의 패스 만 수행하므로 이러한 함수를 정의 할 것인지 알지 못하기 때문일 것입니다 .

함수 문 구문을 사용한 경우

function foo(){ ... }

실제로 함수를 선언하는 위치에는 차이가 없습니다 (항상 선언이 시작 부분에있는 것처럼 동작 함).

반면에 함수가 일반 변수처럼 설정된 경우

var foo = function() { ... };

초기화 전에 호출하지 않도록 보장해야합니다 (실제로 버그의 원인이 될 수 있음).


수많은 코드를 재정렬하는 것은 복잡하고 그 자체로 버그의 원인이 될 수 있으므로 해결 방법을 검색하는 것이 좋습니다. 선언되지 않은 항목에 대해 불평하지 않도록 JSLint에게 전역 변수의 이름을 미리 알려줄 수 있다고 확신합니다.

파일 시작에 대한 주석을 달아주세요.

/*globals foo1 foo2 foo3*/

또는 거기에 텍스트 상자를 사용할 수 있습니다. (저는 또한 당신이 그것에 간섭 할 수 있다면 당신이 내부 jslint 함수에 대한 인수에 이것을 전달할 수 있다고 생각합니다.)


감사. 그럼 / * globals * / 줄이 작동할까요? 좋아-JsHint가 나를 좋아하게 만드는 모든 것. 아직 JavaScript를 처음 사용하고 페이지를 새로 고칠 때 설명 할 수없는 일시 중지가 발생하지만보고 된 버그는 없습니다. 그래서 해결책은 모든 규칙에 따라 플레이 한 다음 여전히 발생하는지 확인하는 것입니다.
Chris Tolworthy 2011 년

4

JavaScript 작성 방법에 대한 임의의 규칙을 추진하는 사람들이 너무 많습니다. 대부분의 규칙은 완전히 쓰레기입니다.

함수 호이 스팅은 좋은 아이디어이기 때문에 JavaScript의 기능입니다.

내부 함수의 유틸리티 인 내부 함수가있을 때 외부 함수의 시작 부분에 추가하는 것은 코드 작성에 허용되는 스타일이지만 세부 정보를 읽어야하는 단점이 있습니다. 외부 기능이 수행합니다.

코드베이스 전체에서 하나의 원칙을 고수해야합니다. 전용 함수를 모듈이나 함수에서 맨 처음 또는 마지막에 두십시오. JSHint는 일관성을 강화하는 데 유용하지만 다른 사람들의 엉뚱한 코딩 개념에 맞게 소스 코드를 조정하지 말고 필요에 맞게 .jshintrc를 절대적으로 조정해야합니다.

야생에서 볼 수있는 한 가지 코딩 스타일은 이점이없고 가능한 리팩토링 고통 만 제공하므로 피해야합니다.

function bigProcess() {
    var step1,step2;
    step1();
    step2();

    step1 = function() {...};
    step2 = function() {...};
}

이것이 바로 피해야 할 기능 호이 스팅입니다. 언어를 배우고 그 강점을 활용하십시오.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.