Почему arguments.callee.caller свойство удерживалось от использования в JavaScript?

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

212
задан Kara 18 March 2014 в 12:22
поделиться

3 ответа

Ранние версии JavaScript не позволили названные выражения function, и из-за этого мы не могли сделать выражение рекурсивной функции:

 // 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;
 });

Однако это было на самом деле действительно плохим решением, поскольку это (в сочетании с другими аргументами, вызываемым и проблемами вызывающей стороны) делает встраивание и хвостовую рекурсию невозможными в общем случае (можно достигнуть его в избранных случаях посредством трассировки и т.д., но даже лучший код sub оптимальный из-за проверок, которые иначе не были бы необходимы). Другая главная проблема - то, что рекурсивный вызов получит различное 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 решил эти вопросы путем разрешения названный выражениями function, например:

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

Это обладает многочисленными преимуществами:

  • функция может быть вызвана как любой другой из Вашего кода.

  • Это не загрязняет пространство имен.

  • значение this не изменяется.

  • Это более производительно (доступ , объект arguments является дорогим).

Возгласы,

Просто поняли, что в дополнение ко всему остальному вопрос был [приблизительно 118], или более конкретно Function.caller .

В любом моменте времени можно найти самую глубокую вызывающую сторону любой функции на стеке, и как я сказал выше, смотрение на стек вызовов имеет один единственный главный эффект: Это делает большое количество из оптимизации невозможным, или намного намного более трудным.

, Например, если мы не можем гарантировать, что функция f не вызовет неизвестную функцию, тогда не возможно встроить f. В основном это означает, что любой сайт вызова, который, возможно, был тривиально inlinable, накапливает большое количество защиты, возьмите:

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

, Если js интерпретатор не может гарантировать, что всеми обеспеченными аргументами являются числа в точке, что вызов выполняется, он должен или вставить проверки на все аргументы перед встроенным кодом, или он не может встроить функцию.

Теперь в данном случае умный интерпретатор должен быть в состоянии перестроить проверки, чтобы быть более оптимальным и не проверить любые значения, которые не использовались бы. Однако во многих случаях это просто не возможно, и поэтому становится невозможно встроить.

250
ответ дан Pacerier 23 November 2019 в 04:30
поделиться

Лучше использовать именованные функции , чем arguments.callee:

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

лучше, чем

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

, именованная функция будет иметь доступ к своей вызывающей стороне через вызывающая сторона свойство:

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

, который лучше, чем

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

, депрекация происходит из-за текущего ECMAScript принципы разработки .

29
ответ дан Zach 23 November 2019 в 04:30
поделиться

arguments.call ee .call er не устарел, хотя он использует функцию .call er свойство. ( arguments.call ee просто даст вам ссылку на текущую функцию)

  • Function.call er , хотя и нестандартный в соответствии с ECMA3, реализован в все основные текущие браузеры .
  • arguments.call er не рекомендуется в пользу Function.call er , и не реализована в некоторых основных браузерах (например, Firefox 3).

Таким образом, ситуация далеко не идеальная, но если вы хотите получить доступ к вызывающей функции в Javascript во всех основных браузерах, вы можете использовать Function.call er свойство,

89
ответ дан 23 November 2019 в 04:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: