让函数中的接收器默认为全局对象背后的基本原理是什么?

What was the rationale behind having the receiver in functions default to the global object?

本文关键字:是什么 背后 全局 函数 接收器 默认 对象      更新时间:2023-09-26

在早期版本的JavaScript中,将receiver(又名context)默认为全局对象背后的理由是什么?

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

Brendan Eich回答:

以便顶级函数(首次发布中唯一的一种)可以起作用作为窗口或框架(后来称为 iframe)方法。还在用。

JS行话nit:"接收器"是语言中的标准OO术语这影响了JS,而不是高度超载的"上下文"。

向布伦丹·艾希提出的问题:

所以ES1没有方法?(参见您对顶级FNS的评论)

布伦丹·艾希:

不,95 年的 JS1(当时没有"ES")有通过函数值属性,但所有函数都是顶级的。ES1 标准化。

99年的ES3增加了函数表达式和嵌套函数(关闭),在这 10 天内我没有时间实施。

回到原始 q:在窗口 w 中,函数 m(){} 使 w.m()可从其他可访问的窗口/框架调用,this == w。

这样顶级函数就可以作为裸函数(即不是方法)从与同一"top"窗口关联的其他窗口和框架中简单调用。

例如,如果页面包含两个框架,则每个框架定义自己的函数foo,用于记录全局对象的属性。这样:

索引.html:

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

框架1.html

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

框架2.html

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

如果我们现在从索引运行以下内容.html:

var foo1, foo2;
foo1 = window.top.Frame1.foo;
foo2 = window.top.Frame2.foo;
foo1(); // "window object one!"
foo2(); // "window object two!"

因此,我们可以看到接收器默认为函数上下文的全局对象。

另一种实现是让裸函数将接收器默认为 undefined,但在 JavaScript 的早期,AFAICT 这被认为是"不太方便"的。请记住,JS最初是为非专业开发人员开发的。

当我们问,为什么这种行为扩展到嵌套函数和函数表达式(在 ES3 中标准化,但事先实现)时,这个问题变得更加有趣?根据阅读Brendan Eich的回答,我的猜测是,在开发嵌套函数和函数表达式时,这根本不是一个公认的问题,因此使用了基于顶级函数的现有行为。

这个问题直到 ES5 中才正式承认"use strict"