foo = function bar() {
alert(2)
}
바(); // 2
foo() // 1
이러한 행동은 "논리적으로" 설명될 수도 있습니다. 컨텍스트 단계에 들어가면 마지막으로 만난 FD 막대가 생성되는데, 이는 Alert(2)를 포함하는 함수입니다. 그 후, 코드 실행 단계에서 새로운 함수인 FE bar가 생성되고 이에 대한 참조가 변수 foo에 할당됩니다. foo를 활성화하면 경고(1)가 생성됩니다. 논리는 명확하지만 IE 버그로 인해 "논리적으로"라는 단어 주위에 따옴표를 붙였습니다. 실행이 분명히 중단되고 JScript 버그에 의존하기 때문입니다.
JScript의 다섯 번째 버그는 정규화되지 않은 식별자(즉, var 키워드 없이)에 할당하여 생성되는 전역 개체의 속성 생성과 관련이 있습니다. 여기서 NFE는 FD로 처리되므로 함수 이름이 동일한 경우 변수 개체에 저장되고 정규화되지 않은 식별자(즉, 변수가 아니라 전역 개체의 일반 속성)가 할당됩니다. unqualified는 동일한 식별자를 가지므로 속성은 전역이 아닙니다.
(function () {
/ / var가 필요하지 않습니다. 그렇다면 현재 컨텍스트의 변수가 아닙니다.
// 전역 개체의 속성입니다.
foo = function foo() {}
})(); 🎜>// 그러나 익명 함수 외부에서는 foo라는 이름을 사용할 수 없습니다.
alert(typeof foo); // 정의되지 않음
"논리"는 이미 명확합니다. context 단계에서 함수는 foo가 익명 함수의 로컬 컨텍스트의 활성 객체를 획득했다고 선언합니다. 코드 실행 단계에서 foo라는 이름은 이미 AO에 존재합니다. 즉, 지역 변수로 처리됩니다. 따라서 할당 작업에서는 ECMA-262-3의 로직에 따라 전역 객체의 새로운 속성을 생성하는 것이 아니라, AO에 이미 존재하는 foo 속성을 간단히 업데이트합니다.
함수 생성자를 통해 생성된 함수
이런 함수 객체도 고유한 특성을 갖고 있으므로 FD, FE와 구분합니다. 주요 특징은 이 함수의 [[Scope]] 속성에 전역 개체만 포함된다는 것입니다.
var x = 10;
function foo() {
var x = 20;
var y = 30; 경고(x) ; 경고(y);');
bar(); // 10, "y"는 정의되지 않았습니다
}
] 함수 표시줄 속성에 foo 컨텍스트의 Ao가 포함되어 있지 않습니다. 변수 'y'에 액세스할 수 없으며 변수 'x'는 전역 개체에서 가져옵니다. 그런데 Function 생성자는 new 키워드와 함께 또는 없이 사용될 수 있으므로 이러한 변형은 동일합니다.
이 기능의 다른 기능은
Equated Grammar Productions
및 Joined Objects와 관련이 있습니다. 사양은 이러한 메커니즘을 최적화 권장 사항으로 제공합니다(그러나 구현에서는 최적화를 사용하지 않을 수 있습니다). 예를 들어 함수 루프 내에서 100개 요소의 배열이 있는 경우 실행 시 결합된 개체 메커니즘을 사용할 수 있습니다. 결과적으로 배열의 모든 요소에 대해 하나의 함수 개체만 사용할 수 있습니다.
var a = [];
for (var k = 0; k < 100; k ) {
a[k] = function () {} // 결합된 객체를 사용할 수 있습니다
}
그러나 함수 생성자를 통해 생성된 함수는 연결되지 않습니다.
for (var k = 0; k < 100; k ) {
a[k] = Function('') // 항상 100개의 다른 함수가 있습니다
}
결합된 객체와 관련된 또 다른 예:
코드 복사
function bar(z) {
return z * z
}
return bar
}
var; x = foo();
var y = foo()
여기서의 구현에는 함수(내부 [[Scope]] 속성 포함)가 근본적으로 구별할 수 없기 때문에 객체 x와 객체 y(동일한 객체 사용)를 연결할 수 있는 권한도 있습니다. 따라서 함수 생성자를 통해 생성된 함수에는 항상 더 많은 메모리 리소스가 필요합니다.
함수 생성 알고리즘
아래 의사코드는 함수 생성 알고리즘을 설명합니다(공용체 개체와 관련된 단계 제외). 이러한 설명은 ECMAScript의 함수 개체에 대한 자세한 내용을 이해하는 데 도움이 됩니다. 이 알고리즘은 모든 함수 유형에 적합합니다.
F = new NativeObject()
// 속성 [[Class]]는 "Function"
F.[[Class]] = "Function"
// 함수 객체의 프로토타입은 Function <의 프로토타입입니다. 🎜>F.[[ Prototype]] = Function.prototype
// 함수 자체가 사용됩니다
// 표현식 F를 호출할 때 [[Call]]을 활성화하고
// new 실행 컨텍스트
F.[[Call]] = <함수 참조>
// 객체의 일반 생성자에서 컴파일
// [[Construct]] new를 통해 활성화 키워드
// 새 객체에 메모리를 할당합니다
// 그런 다음 F.[[Call]]을 호출하여 새로 생성된 객체를 초기화합니다.
F.[[Construct]] = InternalConstructor
// 현재 실행 컨텍스트 범위 체인
// 예를 들어 F의 컨텍스트를 생성합니다
F.[[Scope]] = activeContext.Scope
// new를 통해 함수가 생성되는 경우 Function(...),
// 그러면
F.[[Scope]] = globalContext.Scope
// 전달된 매개변수 개수
F.length = countParameters
// F 객체 생성의 프로토타입
__objectPrototype = new Object();
__objectPrototype.constructor = F // {DontEnum}, 루프에서 열거할 수 없음 x
F.prototype = __objectPrototype
return F
F.[[Prototype]]은 함수(생성자)의 프로토타입이고, F.prototype은 이에 의해 생성된 객체의 프로토타입이라는 점에 유의하세요. 함수(용어가 종종 혼동되기 때문에 일부 기사에서는 F.prototype을 "생성자 프로토타입"이라고 부르는데 이는 올바르지 않습니다).
결론
글이 좀 깁니다. 하지만 다음 장에서 객체와 프로토타입에 대한 함수에 대해 계속 논의하면서 의견에 있는 질문에 다시 답변해 드리겠습니다.
기타 참고자료
13. — - 기능 정의;
15.3 —
- 함수 개체