[javascript] arguments.callee.caller 속성이 JavaScript에서 더 이상 사용되지 않는 이유는 무엇입니까?

arguments.callee.callerJavaScript 에서 속성이 더 이상 사용되지 않는 이유는 무엇 입니까?

JavaScript에서 추가 된 후 더 이상 사용되지 않지만 ECMAScript에서는 완전히 생략되었습니다. 일부 브라우저 (Mozilla, IE)는 항상 해당 브라우저를 지원했으며 지원을 제거 할 계획이 없습니다. 다른 사람들 (Safari, Opera)은 이에 대한 지원을 채택했지만 이전 브라우저에서의 지원은 신뢰할 수 없습니다.

이 귀중한 기능을 림보에 넣을만한 충분한 이유가 있습니까?

(또는 대안으로, 호출 기능을 처리하는 더 좋은 방법이 있습니까?)



답변

JavaScript의 초기 버전에서는 명명 된 함수 표현식이 허용되지 않았기 때문에 재귀 함수 표현식을 작성할 수 없었습니다.

 // This snippet will work:
 function factorial(n) {
     return (!(n>1))? 1 : factorial(n-1)*n;
 }
 [1,2,3,4,5].map(factorial);


 // But this snippet will not:
 [1,2,3,4,5].map(function(n) {
     return (!(n>1))? 1 : /* what goes here? */ (n-1)*n;
 });

이 문제를 해결하기 위해 arguments.callee추가되었습니다.

 [1,2,3,4,5].map(function(n) {
     return (!(n>1))? 1 : arguments.callee(n-1)*n;
 });

그러나 이것은 실제로 다른 해결책, 수신자 및 발신자 문제와 관련하여 일반적인 경우에는 인라인 및 꼬리 재귀를 불가능하게하므로 실제로는 나쁜 해결책이었습니다 (추적 등을 통해 특정 경우에 달성 할 수는 있지만 최상의 코드조차도 가능합니다) 그렇지 않으면 필요하지 않은 점검으로 인해 최적이 아님). 다른 주요 문제는 재귀 호출이 다른 this값 을 얻는다는 것 입니다. 예를 들면 다음과 같습니다.

var global = this;
var sillyFunction = function (recursed) {
    if (!recursed)
        return arguments.callee(true);
    if (this !== global)
        alert("This is: " + this);
    else
        alert("This is the global");
}
sillyFunction();

어쨌든 EcmaScript 3는 다음과 같은 명명 된 함수 표현식을 허용하여 이러한 문제를 해결했습니다.

 [1,2,3,4,5].map(function factorial(n) {
     return (!(n>1))? 1 : factorial(n-1)*n;
 });

이것은 많은 이점이 있습니다 :

  • 함수는 코드 내부에서 다른 것과 같이 호출 할 수 있습니다.

  • 네임 스페이스를 오염시키지 않습니다.

  • 값은 this변경되지 않습니다.

  • 성능이 뛰어납니다 ( arguments 객체에 액세스하는 것이 비쌉니다).

으악,

그 질문은 다른 모든 것에 더해 arguments.callee.caller또는 더 구체적 이라는 것을 깨달았습니다 Function.caller.

어느 시점에서나 스택에서 함수의 가장 깊은 호출자를 찾을 수 있으며 위에서 언급했듯이 호출 스택을 보는 데는 하나의 주요 효과가 있습니다.

예 : 함수 f가 알 수없는 함수를 호출하지 않을 것이라고 보장 할 수 없으면 인라인 할 수 없습니다 f. 기본적으로 그것은 사소하게 불쾌했을 수있는 모든 호출 사이트에 많은 수의 경비원이 축적됨을 의미합니다.

 function f(a, b, c, d, e) { return a ? b * c : d * e; }

js 인터프리터가 제공된 모든 인수가 호출 시점의 숫자임을 보장 할 수 없으면 인라인 코드 앞에 모든 인수에 대한 검사를 삽입하거나 함수를 인라인 할 수 없습니다.

이제이 특별한 경우에, 스마트 통역사는보다 최적의 수표를 재 배열하고 사용할 수없는 값을 검사하지 않을 수 있어야합니다. 그러나 많은 경우에 그것은 가능하지 않으므로 인라인하는 것이 불가능합니다.


답변

arguments.callee.caller있다 없다 가의 메이크업을 사용하지 불구하고 사용되지 않는 속성을. ( 현재 기능에 대한 참조를 제공합니다)Function.callerarguments.callee

  • Function.callerECMA3에 따르면 비표준이지만 현재 모든 주요 브라우저에서 구현 됩니다.
  • arguments.caller 더 이상 사용되지 않으며 일부 현재 주요 브라우저 (예 : Firefox 3)에서는 구현되지 않습니다.Function.caller

따라서 상황이 이상적이지는 않지만 모든 주요 브라우저에서 Javascript로 호출 함수에 액세스하려는 경우 이름 지정된 함수 참조에서 직접 액세스하거나 특성을 통해 익명 함수 내에서 특성을 사용할 수 있습니다.Function.callerarguments.callee


답변

arguments.callee보다 명명 된 함수 를 사용하는 것이 좋습니다 .

 function foo () {
     ... foo() ...
 }

~보다 낫다

 function () {
     ... arguments.callee() ...
 }

명명 된 함수는 호출자 속성을 통해 호출자에게 액세스 할 수 있습니다.

 function foo () {
     alert(foo.caller);
 }

어느 것보다 낫다

 function foo () {
     alert(arguments.callee.caller);
 }

더 이상 사용되지 않는 것은 현재 ECMAScript 설계 원칙 때문 입니다.


답변

확장명입니다. “this”의 값은 재귀 중에 변경됩니다. 다음 (수정 된) 예에서 factorial은 {foo : true} 객체를 가져옵니다.

[1,2,3,4,5].map(function factorial(n) {
  console.log(this);
  return (!(n>1))? 1 : factorial(n-1)*n;
},     {foo:true}     );

처음 호출 된 계승은 객체를 가져 오지만 재귀 호출에는 해당되지 않습니다.


답변