arguments.callee.caller 속성이 JavaScript에서 더 이상 사용되지 않는 이유는 무엇입니까?
arguments.callee.caller
JavaScript 에서 속성이 더 이상 사용되지 않는 이유는 무엇 입니까?
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 ofFunction.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.
'Programing' 카테고리의 다른 글
MSSQL 오류 '기본 공급자가 열리지 못했습니다.' (0) | 2020.04.30 |
---|---|
TSQL에서 PRINT 버퍼를 어떻게 플러시합니까? (0) | 2020.04.30 |
HTML 버튼을 사용하여 JavaScript 함수 호출 (0) | 2020.04.30 |
ASP.NET MVC 응용 프로그램 성능을 개선하려면 어떻게합니까? (0) | 2020.04.30 |
루트 액세스없이 파이썬 모듈을 설치하는 방법은 무엇입니까? (0) | 2020.04.30 |