zoukankan      html  css  js  c++  java
  • JavaScript随笔(三):JS也有入口函数Main

    在C和Java中,都有一个程序的入口函数或方法,即main函数或main方法。而在JavaScript中,程序是从JS源文件的头部开始运行的。但是某种意义上,我们仍然可以虚构出一个main函数来作为程序的起点,这样一来不仅可以跟其他语言统一了,而且说不定你会对JS有更深的理解。

    1. 实际的入口

    当把一个JavaScript文件交给JS引擎执行时,JS引擎就是从上到下逐条执行每条语句的,直到执行完所有代码。

    2. 作用域链、全局作用域和全局对象

    我们知道,JS中的每个函数在执行时都会产生一个新的作用域。具体来说,在执行流程进入函数时会建立一个新的作用域,在函数执行完成退出时会销毁这个作用域。函数的形参、局部变量都会绑定到这个作用域里,当函数调用完成作用域销毁时,它们随之被销毁。当然在特殊情况下,如果函数返回时作用域中的某些变量仍然被引用,那么作用域以及这些被引用的变量就不会被销毁,从而形成所谓的闭包

    另一方面,我们知道函数是可以嵌套的,因而作用域也是可以嵌套的。函数在定义的时候,JS引擎会给每个函数设置一个称为[[scope]]内置属性,它指向外部函数的词法作用域。通过这种方式,多个作用域形成了链式结构,称为作用域链。通常情况下,在任意时刻只存在一条作用域链,即从正在执行的函数的作用域开始,层层上溯,直到最外层的全局作用域

    [注]:作用域链上的函数就是JS源码里的层层嵌套的函数,跟函数执行时的顺序或函数调用栈无关,这也是词法作用域这个称呼的由来。

    全局作用域是一个特殊的作用域,它不是一个函数作用域,但它是所有函数作用域的外层作用域,也是所有作用域链的终点。因此只要程序没有退出,全局作用域总是存在的,全局作用域内的变量也是一直有效的。

    [函数3的作用域]-->[函数2的作用域]-->[函数3的作用域]-->[全局作用域]

    另外,对应于全局作用域,还有一个全局对象。在浏览器中,全局对象就是window对象。全局对象是个特殊的对象:

    • 在全局作用域中定义的变量,都会绑定到全局对象。
    • 在任意作用域中定义的变量,如果定义时没有用 var 关键字,都会绑定到全局对象。
    • 在全局作用域中, this 指向全局对象。

    从上面列举的这些特性可以看出,如果把全局作用域当成一个对象的话,那么实际上它就是全局对象。另外,这也解释了在全局作用域中,下面的四条语句为什么是等价的:

    var a = 1; // 绑定到当前作用域(在这里就是全局作用域)
    a = 1; // 绑定到全局作用域
    window.a = 1; // 绑定到全局对象
    this.a = 1; // 绑定到this

    3. 虚构的main函数

    既然都是作用域,为什么要有一个特殊的全局作用域呢?我们总是喜欢简单化、一致性,而尽量避免复杂化、特殊性。所以很自然地,我们会想能否让全局作用域看起来跟函数作用域没什么区别?答案是肯定的。我们可以做这样的构想:

    我们假设,在JS引擎执行源文件时,会将文件中的代码包装到一个叫做main的函数中。然后把这个main函数作为程序的入口。

    也就是说,假设一个JS文件中有这样的代码:

    var a = 1;
    var b = 2;
    
    function add(x, y) {
        var z = x + y;
        return z;
    }
    
    console.log(add(a, b));

    JS引擎在程序开始执行前会把它包装成一个main函数:

    // 虚构的main函数
    function main() {
        var a = 1;
        var b = 2;
    
        function add(x, y) {
            var z = x + y;
            return z;
        }
    
        console.log(add(a, b));
    } 

    然后,调用这个main函数:

    main._current_scope_ = window; // 将全局作用域(对象)设为window
    main.call(window) // 将this指向window

    4. 意义何在?

    (1) JS也有了入口函数main,跟其他语言一致了。

    (2) 省去了全局作用域的概念,或者说全局作用域也成了函数作用域。

    (3) 通过上面对main函数的调用过程,可以明白全局作用域中的那些特殊性质的由来。

    (4) 最后一点,将所有JS源码当成一个函数,是为了后面讲事件队列、事件循环做铺垫。

  • 相关阅读:
    【PowerDesigner】【2】将工具栏显示出来
    【PowerDesigner】【1】简单介绍
    【服务器】【Windows】【4】删除Windows系统中不想要的服务
    【Java】【8】StringUtils中isNotEmpty和isNotBlank的区别
    【Java】【7】枚举类
    hdu 1285
    Codeforces Round #198 (Div. 2) —— D
    Codeforces Round #198 (Div. 2) —— C
    Codeforces Round #198 (Div. 2) —— B
    Codeforces Round #198 (Div. 2) —— A
  • 原文地址:https://www.cnblogs.com/manxisuo/p/JS-Note-3-Imaginary-Main-Function.html
Copyright © 2011-2022 走看看