Programing

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

lottogame 2020. 4. 30. 07:26
반응형

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 객체에 액세스하는 것이 비쌉니다).

으악,

Just realised that in addition to everything else the question was about arguments.callee.caller, or more specifically Function.caller.

At any point in time you can find the deepest caller of any function on the stack, and as I said above, looking at the call stack has one single major effect: It makes a large number of optimizations impossible, or much much more difficult.

Eg. if we can't guarantee that a function f will not call an unknown function, then it is not possible to inline f. Basically it means that any call site that may have been trivially inlinable accumulates a large number of guards, take:

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

If the js interpreter cannot guarantee that all the provided arguments are numbers at the point that the call is made, it needs to either insert checks for all the arguments before the inlined code, or it cannot inline the function.

Now in this particular case a smart interpreter should be able to rearrange the checks to be more optimal and not check any values that would not be used. However in many cases that's just not possible and therefore it becomes impossible to inline.


arguments.callee.caller is not deprecated, though it does make use of the Function.caller property. (arguments.callee will just give you a reference to the current function)

  • Function.caller, though non-standard according to ECMA3, is implemented across all current major browsers.
  • arguments.caller is deprecated in favour of Function.caller, and isn't implemented in some current major browsers (e.g. Firefox 3).

So the situation is less than ideal, but if you want to access the calling function in Javascript across all major browsers, you can use the Function.caller property, either accessed directly on a named function reference, or from within an anonymous function via the arguments.callee property.


It is better to use named functions than arguments.callee:

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

is better than

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

The named function will have access to its caller through the caller property:

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

which is better than

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

The deprecation is due to current ECMAScript design principles.


Just an extension. The value of "this" changes during recursion. In the following (modified) example, factorial gets the {foo:true} object.

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

factorial called first time gets the object, but this is not true for recursive calls.

참고URL : https://stackoverflow.com/questions/103598/why-was-the-arguments-callee-caller-property-deprecated-in-javascript

반응형