Каково было обоснование того, что получатель в функциях по умолчанию использует глобальный объект?

В ранних версиях JavaScript было обосновано, что по умолчанию для receiver (aka context) для глобального объекта?

function a() {
  console.log(this); // window
}

Ответы

Ответ 1

Brendan Eich ответил:

Так что функции верхнего уровня (единственный вид в первом выпуске) могут действовать как окна или рамки (позже, iframe). Все еще используется.

JS jargon nit: "приемник" - стандартный термин OO в языках что повлияло на JS, а не на сильно перегруженный "контекст".

Вопрос, заданный Брендану Эиху:

Итак, у ES1 не было методов? (cf ur комментарий на верхнем уровне fns)

Брендан Эйх:

Нет, JS1 в '95 (тогда нет "ES" ) имели методы через функциональнозначные свойства, но все функции были верхнего уровня. Стандарт ES1.

ES3 в '99 добавлены функциональные выражения и вложенные функции (закрытия), которые я не успел реализовать за эти 10 дней.

Чтобы вернуться к началу q: в окне w функция m() {} делает w.m() вызываемый из других доступных окон/кадров с this == w.

Ответ 2

Таким образом, функции верхнего уровня можно было бы тривиально вызывать как голые функции (т.е. не как методы) из других окон и фреймов, связанных с одним и тем же "верхним" окном.

Например, если страница содержит два кадра, каждая из которых определяет свою собственную функцию foo, которая регистрирует свойство глобального объекта. Например:

index.html

<html>
  <title>index.html</title>
  <frameset cols="30%,70%">
    <frame name="Frame1" src="frame1.html">
    <frame name="Frame2" src="frame2.html">
  </frameset>

frame1.html

<html>
  <title>frame1.html</title>
  <script>
    function foo() {
      console.log('frame1::foo: ', this.id);
    }
    this.id = 'window object one!';
  </script>

frame2.html

<html>
  <title>frame2.html</title>
  <script>
    function foo() {
      console.log('frame2::foo: ', this.id);
    }
    this.id = 'window object two!';
  </script>

Если теперь мы запустим следующее из index.html:

var foo1, foo2;
foo1 = window.top.Frame1.foo;
foo2 = window.top.Frame2.foo;

foo1(); // "window object one!"
foo2(); // "window object two!"

Итак, мы видим, что получатель по умолчанию использует глобальный объект контекста функции.

Альтернативная реализация заключалась бы в том, чтобы иметь незаполненные функции, по умолчанию получателя undefined, но AFAICT это воспринималось как "менее удобный" в первые дни JavaScript. Помните, что JS была первоначально разработана с учетом непрофессиональных разработчиков.

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

Вопрос был официально признан в ES5 с "use strict".