JavaScript学习笔记(三):JavaScript也有⼊⼝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;
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));
}
javascript 函数
然后,调⽤这个main函数:
main._current_scope_ = window; // 将全局作⽤域(对象)设为window
main.call(window) // 将this指向window
4. 意义何在?
(1) JS也有了⼊⼝函数main,跟其他语⾔⼀致了。
(2) 省去了全局作⽤域的概念,或者说全局作⽤域也成了函数作⽤域。
(3) 通过上⾯对main函数的调⽤过程,可以明⽩全局作⽤域中的那些特殊性质的由来。
(4) 最后⼀点,将所有JS源码当成⼀个函数,是为了后⾯讲事件队列、事件循环做铺垫。
以上就是⼩编给⼤家介绍的JavaScript学习笔记(三):JavaScript也有⼊⼝Main函数,希望⼤家喜欢。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。