Каково было обоснование того, что получатель в функциях по умолчанию использует глобальный объект?
В ранних версиях 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"
.