Устаревшая собственность вызывающего в браузерах - PullRequest
0 голосов
/ 14 января 2020

Экспериментируя с устаревшим свойством "caller", я столкнулся с необычным поведением в браузерах. Были использованы следующие браузеры: Google Chrome 79.0.3945.117, Firefox 72.0.1, Edge 44.18362.449.0

Давайте начнем с базового c примера:

function start(){}
start.hasOwnProperty("caller")

Google Chrome: true , Firefox: false, Edge: true

Что ж, правда в том, что только в Firefox не используется свое собственное свойство "caller" для каждой объявленной функции.

В таком примере:

function start(){"use strict"};
start.hasOwnProperty("caller")

Google Chrome: false, Firefox: false, Edge: false


Давайте посмотрим на следующее код

function a(){b()}
function b(){"use strict";c()}
function c(){console.log(c.caller)}
delete Function.prototype.caller;
a()

А что мы видим? Мы видим, что в Edge возникает только ошибка, и Google Chrome скрывает ее, показывая нам значение null, Firefox возвращает неопределенное значение, поскольку не может найти такое свойство с именем "caller" где-либо.

Хотя этот случай описывается спецификацией как:

Если реализация расширяет любой функциональный объект собственным свойством с именем "caller", значение этого свойства, как наблюдается с использованием [[Get]] или [ [GetOwnProperty]], не должен быть строгим функциональным объектом. Если это свойство доступа, то функция, которая является значением атрибута свойства [[Get]], никогда не должна возвращать строгую функцию при вызове.

Если мы выполним приведенный выше код, но удалим "use strict" затем в Google Chrome и Edge мы заметим, что запись console.log (c.caller) дает нам функцию, которая вызывает текущую функцию, и это, если в Function.prototype отсутствует свойство "caller". Но Firefox в этой ситуации молчит и выдает тот же результат, что и в строгом режиме - "undefined".

Кстати, если мы удалим прототипы этих функций, ничего не изменится:

function a(){b()}
function b(){"use strict";c()}
function c(){console.log(c.caller)}
delete Function.prototype.caller;
Object.setPrototypeOf(a,null);
Object.setPrototypeOf(b,null);
Object.setPrototypeOf(c,null);
a();

С Firefox все предельно просто:

  1. В строгом режиме
    1. Свойство "caller" не определено для функции
    2. При вызове свойства "caller" свойство берется из Function.prototype
    3. При вызове свойства "caller" выдается ошибка.
  2. В обычном режиме
    1. Свойство "caller" не определено для функции
    2. При вызове свойства "caller" свойство берется из Function.prototype
    3. Вызов свойства "caller" не выведите ошибку.

Хотя Firefox тоже не так просто. Спецификация гласит следующее: https://tc39.es/ecma262/#sec -адресная функция-свойства . То есть спецификация говорит, что вам нужно определить свойства с ошибками в Function.prototype при их вызове. Спецификация четко определяет свойство аксессора "caller" как свойство, которое содержит ошибку. Но Firefox в обычном режиме свойство «вызывающий» кажется переопределенным или изначально определенным для двух типов кода: строгий и не строгий. Является ли это поведение ошибкой Firefox реализации?

Относительно Google Chrome и Edge:

  1. В строгом режиме
    1. Свойство "caller" не определено для функции
    2. При вызове свойства "caller" свойство берется из Function.prototype
    3. При вызове свойства caller возникает ошибка.
  2. В обычном режиме
    1. Свойство "caller" определяется для функции
    2. Когда вызывается свойство "caller", свойство не берется из Function.prototype (где?)
    3. Вызов свойства "caller" не приводит к ошибке.

Самым непонятным в этой ситуации является то, как Google Chrome и Edge получают значение для свойства "caller" с удаленным Function.prototypeFunction.prototype есть метод получения и установки свойства "caller", а в обычной функции свойство "caller" не имеет ни метода получения, ни установки)?

1 Ответ

0 голосов
/ 14 января 2020

Свойство function.caller возвращает функцию, которая вызвала указанную функцию. Это свойство запрещено в строгом режиме .

...