返回介绍

4.5 你真的理解这行代码吗?

发布于 2024-12-15 23:01:44 字数 3299 浏览 0 评论 0 收藏 0

绑定有很多种情况,几乎所有在程序代码中用到的标识,都存有绑定的问题。最常见的例如变量 9

var aNum = 100;

上述一句代码(的语法),对应着三个语义:

  1. 有一个标识,记为 aNum
  2. 标识所指代的数据,其值是可变的(即,变量);
  3. 该数据当前值为 100。

对于大多数语言来说,第二个语义是一项执行过程中的限制,亦即表明任何可以访问到 aNum 标识的代码都可以改变它的值。为了简便,我们暂不讨论这一个语义的绑定问题。但第一、三个语义所述的:

有标识 aNum ,其数据当前值为 100

就明显作用于我们的计算:如果数据无值,或值不确定,则我们无法进行后续的计算过程。所以对于代码 aNum = 100 ,其在语义上的“值 100”将在何时被绑定到标识 aNum ,就是一个相当重要的问题。

以一个代码片段来看(相信我,这是实际可运行的代码):

1
2
3
4
5
  // 代码1
  function process_part_one() {
    aNum = aNum * 2;
    var aNum = 100;
  }

根据我们对这段代码的语法约定,第2、5行决定了代码片段中的标识符的生存周期 10 。但在这个生存周期中, aNum 是何时有“值 100”的含义的呢?

对于这个问题,一些语言认为,表达“ aNum 变量具有初值 100”这样的语义,应该是计算过程的 前设 ,即对计算前提条件的声明。而声明并不是计算,因此声明语法与执行语法也应当分别对待。例如 Pascal,就处理为这样的语法(在 var 部分做声明,在 begin...end 部分处理执行):

1
2
3
4
5
6
7
  // 代码2, pascal 风格
  procedure process_part_one;
  var
    aNum = 100;
  begin
    aNum := aNum * 2;
  end;

另一些语言则认为,声明语法可以理解为对执行环境的预置,也有执行含义,因此可以允许“即用即声明”,例如 C。但是语义上,这是因“(需)即用”而进行的声明,不可能出现“已用”而未声明的情况。所以即使 C 语言,也会因为语义上无法解释,而判断上述代码 1 违例。

还有一些语言认为:

var aNum

是一个语义,它只表明标识 aNum 的存在,直到 函数调用 时才绑定另外一个语义:初始操作,亦即是为函数内所有存在的标识进行初始化。在这样的认识下,“代码1”中的

1
2
3
4
  // 代码3
  function process_part_one() {
     var aNum
  }

就具有了完整的语义。这个语义(即“初始操作”)与实际的计算机行为,是在把 process_part_one() 作为 函数调用 时,才进行绑定和实施的。其效果是:

  • 在生命周期(代码3的2~4行,或代码1的2~6行)中,记有一个标识 aNum ;且,
  • 在该标识所处生命周期开始时,总会有一个初始化动作,使该标识具有一个初值: 无值 ;且,
  • 设整个计算环境中, 无值 是一种值,记为 undefined

你可能已经知道,这就是 JavaScript 的实现方法 11 。进一步地,除开上述代码在生命周期上的解释之外,代码1被理解为:

1
2
3
4
5
  // 代码4
  function process_part_one() {
     aNum = aNum * 2; // aNum 有初值,记为 undefined
     aNum = 100;
  }

我们看到,代码1中的语法:

var aNum = 100

所具有的两个语义(本小节开始处的语义 1 和语义 3)被分别绑定在 函数调用开始 和代码4的第4行;且一个标识的初值含义,总是明确地被约定为 undefined 。由此一来,上述代码1整体的语义就确定了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文