2010-05-10 3 views
16

이의 우리가이 코드를 가지고 있다고 가정 해 봅시다 재 컴파일 자바 스크립트 폐쇄 위치 :는 (잠시 프로토 타입에 대해 잊지)

function A(){ 
    var foo = 1; 
    this.method = function(){ 
    return foo; 
    } 
} 
var a = new A(); 

는 내부 함수는 함수 A가 실행될 때마다 다시 컴파일입니까?

function method = function(){ return this.foo; } 
function A(){ 
    this.foo = 1; 
    this.method = method; 
} 
var a = new A(); 

또는 자바 스크립트 엔진마다 새로운 '방법'기능을 만들 않을만큼 똑똑 : 아니면 이런 식으로 작업을 수행하는 것이 좋습니다 (왜)인가? 특히 Google의 v8 및 node.js

또한 어떤 기술을 언제 사용할 수 있는지에 대한 일반적인 권장 사항이 있습니다. 내 구체적인 예를 들어, 첫 번째 예제를 사용하려면 정말 맞는,하지만 그 외부 함수는 여러 번 인스턴스화 된 것을 알고.

+1

흥미로운 질문입니다. 자바 스크립트 인터프리터가 그보다 더 똑똑하다고 내기를 기꺼이하겠다. –

+0

솔직히 말해서 성능에 대해 걱정할 경우 병목 현상이 발생하지 않아야합니다. 나는 그것에 대해 걱정하지 않을 것이다. –

+0

모든 생성자 호출과 함께 복제되지 않는 전용 변수에 getter를 구현하고 싶습니까? – Alsciende

답변

7

필자가 이해할 때마다 함수가 실행될 때마다 다른 "범위"가 있으므로 함수를 "컴파일하는"것이 중요하지 않습니다.

두 번째 방법은 항상 동일한 범위의 method입니다.

첫 번째 방법은 A() 함수 호출의 범위 안에 method을 넣습니다. 따라서 해당 범위 안에있는 모든 정보 (var foo, 함수 매개 변수 등)는 에 저장되며 해당 범위는입니다. 따라서 매번 동일한 기능 코드가 참조되지만 다른 범위 (따라서 다른 "객체")에있게됩니다.

+0

+1, 여기에 가장 우수하고 가장 간결한 대답 (그리고 실제로 질문에 답했습니다!). –

2

이 메서드는 다시 컴파일되지 않습니다.

Javascript 인터프리터는 외부 메서드를 호출 할 때마다 내부 메서드와 로컬 변수를 포함하는 새 클로저 개체를 만듭니다.

정확한 구현은 Javascript 엔진에 따라 다릅니다.

+1

Google v8에 대한 의견이 있으십니까? – disc0dancer

+0

나는 잘 모른다. – SLaks

0

"this"키워드가 실행 컨텍스트를 참조하기 때문에 ... 컴파일러는이를 해석하는 함수에 대해 많이 알 필요가 없기 때문에 단 한 번만 컴파일됩니다. 당신은 함수의 바닥에 변수를 선언 할 때

는 또한, 여전히 상단에 액세스 할 수 있습니다 :

function test() 
{ 
    alert(hello); 
    // ... 
    var hello = 2; 
} 

그것은 기능과 같은 일이다. 나는 A가 호출 될 때마다 다시 컴파일되지 않는다는 것을 염두에 두는 그 두 가지를 믿을 것이다.

마이크

+0

사실 - 이것은 '정의되지 않음'을 경고해야합니다. 변수 선언이 맨 위로 올라 갔지만 경고 다음에야'hello'가'2'로 설정되지 않습니다. –

3

예, A 개체의 인스턴스화마다 새로운 Function 개체가 생성됩니다. 다음과 같이이 문제를 설명 할 수

function A(){ 
    var foo = 1; 
    this.method = function(){ 
    return foo; 
    } 
} 
var a = new A(); 
var b = new A(); 
alert(a.method == b.method); // Returns false; two different Function objects 

이 같은 기능 개체를 재사용하는 방법을 프로토 타입이 아닌 인스턴스의 속성을 확인하려면.

function B() { 
    this.foo = 1; 
} 

B.prototype.method = function() { 
    return this.foo; 
} 

var a = new B(); 
var b = new B(); 
alert(a.method == b.method); // Returns true; it's the same Function object 

편집 : 지금까지 내가 아는 한, 자바 스크립트 객체에서 private 변수를 만드는 제외하고는 첫 번째 버전과 같은 일을 할 이유가 없습니다. 원래 예에서 foo은 비공개입니다. 객체 외부에서 직접 액세스 할 수있는 것은 없습니다.불행히도이 기술을 사용하여 많은 수의 객체를 인스턴스화하면 성능 및 메모리 사용 공간에 영향을 미칠 수 있습니다.

제 코드에서는 "공개"속성과 "개인"속성을 구별하기 위해 명명 규칙을 사용합니다. 나는 첫 번째 문자로 밑줄이있는 사유 재산의 이름을 짓는다. 그래서 myObject._someMethod()과 같은 것을 보면, 나는 틀린 것을 알고 있습니다.


Edit2가 : 그것은 method 속성이 포함 숨겨진 클래스를 생성 할 때 http://code.google.com/apis/v8/design.html에서, 나는, V8 한 번 폐쇄를 컴파일 생각합니다.

+0

이것은 매우 흥미 롭습니다. 평등 연산자가 의도적으로 두 메서드를 구별 할 수 있지만 실제로는 동일합니까? 나는 프로토 타입을 사용할 수 있다는 것을 알고 있지만이 경우에는 무시하고 싶다. – disc0dancer

+2

@Discodancer : 두 가지 메소드는 같은 코드를 가지고 있지만,'a = {}; b = {}; 경고 (a == b); // false'. – jhurshman

+1

로컬 ("개인") 변수를 사용하여 성능이 저하되는 것은 현대 해석기에서는 무시할 수 있습니다. 나는 기억에 관해 모른다. 그러나 나는 거대한 차이를 만들만큼 충분히 크지 않을 것이라고 생각한다. –

0

함수를 다른 객체로 상상해보십시오. 새 객체를 만들면 일부 데이터 변수가 변경된 이전 객체의 복사본 일뿐입니다. 일어날 수 있도록 개체의 소스를 다시 구문 분석 할 필요가 없습니다. 좋은 비유는 루아의 함수 객체 인 C++의 함수형이며 많은 언어를 모릅니다. 기능 변경 때문에

0
function A(){ 
    var foo = 1; 
    this.method = function(){ 
    return foo; 
    } 
} 

function method = function(){ return this.foo; } 
function A(){ 
    this.foo = 1; 
    this.method = method; 
} 

로 컴파일 할 수 없습니다. 첫 번째 예제는 생성자 'A'와 'method'라는 함수에서만 볼 수있는 'foo'변수를 가지고 있고 두 번째 예제에서는 'A'인스턴스에 액세스 할 수있는 모든 항목에서 액세스 할 수 있습니다.

function method = function(){ return 1; } 
function A(){ 
    this.method = method; 
} 

로 컴파일 할 수 있습니다하지만 난 거기 어떤 자바 스크립트 엔진이 그렇게 멀리 갈 것이라고 생각하지 않지만, 당신은에 넣어 전처리 할 파일과 기꺼이하는 경우에 노력의 여분의 비트, 고급 모드에서 사용되는 경우 google closure compiler 꽤 멀리 갈 수 있습니다.

+0

제 질문은 첫 번째 예제가 A()를 실행할 때마다 함수의 새 인스턴스를 생성하는지 아닌지, 아니면 다른 예제로 컴파일 할 수 있는지 여부입니다. – disc0dancer

관련 문제