`

浅析JS全局变量与局部变量 执行环境 作用域链 JS解释器执行过程

阅读更多
参考http://hi.baidu.com/cjry_8854/item/585b445f577aab3494eb0513
这里列出几个值得注意的地方
一全局变量 变量的声明
JS解释器开始运行时,在执行任何JS代码前,会创建一个全局对象,并且JS解析器会在相应的代码段里寻找var声明的变量,把这个var声明的变量作为全局对象的属性(在函数中它也作为调用对象的属性),并初始化为undefined。

也就是说当var声明一个JS全局变量时,实际上就是定义了一个全局对象的属性,或者反过来说,这个全局对象的属性就是JS全局变量。当然JS解释器还会用预定义的值和函数来初始化全局对象的许多属性,如:Infinity parseInt Math。在非函数内部可以用this来引用这个全局对象,还要注意window和this的区别,在客户端的JS中,Window对象代表浏览器窗口,它包含该窗口中的所有JS代码的全局对象,具有自我引用的window属性。

重复的var声明不会造成任何错误 var声明只是方便创建全局对象,调用对象的属性,代码只是赋值用的

遗漏的声明:给未声明的变量赋值,JS会隐式声明全局变量(在全局对象中增加相应的属性),然后给其赋值

二.变量作用域
1.局部变量和全局变量同名时,会隐藏这个全局变量。
2.函数没有块级作用域,函数中声明的变量,无论在哪里声明的,在整个函数中它们都是有定义的。
3.未声明的变量和未赋值的变量:alert(u);会产生一个错误--使用未声明的变量会产生一个错误
var u;alert(u);会跳出undefined---使用未赋值的变量,使用的它的默认值undefined

三 局部变量:调用对象
1.函数的局部变量作为调用对象的属性,调用对象是一个完全独立的对象,它独立于全局对象,所以可以防止覆盖同名的全局变量。

四 JS的执行环境
1.JS解释器执行一个函数时,会创建一个执行环境。JS允许同时存在多个全局执行环境,如:JS客户端的ifame的情况。

执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为。每个执行环境都有一个与之相关联的变量对象,执行环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。
可见http://blog.163.com/tracy_hyq/blog/static/2084161872012529112624447/
这里要注意,在上面的博客中和一些其他书籍中所说的变量对象就可以理解为这里的全局对象和调用对象,那里的活动对象可以理解为这里的调用对象。

五JS的执行过程
具体可参见http://hi.baidu.com/cjry_8854/item/585b445f577aab3494eb0513

在JS解释器执行任何代码之前,创建全局对象
    用预定义的值和函数来初始化全局对象中的属性,eg.Math,Infinity,parseInt
    搜索函数外的var声明,创建全局对象相应的属性,初始化为undefined
  创建全局的执行环境,作用域链只有一个对象-全局对象
  依次执行代码
    遇到var声明赋值语句给全局对象相应的属性赋值
    遇到未声明赋值语句,在全局对象中查找是否已有该属性,如果没有,增加相应的属性,最后赋值
    遇到函数调用,创建调用对象
      搜索函数中的var声明和参数,创建调用对象相应的属性,初始化为undefined
      创建函数执行环境,作用域链--第一对象:调用对象;第二对象:全局对象
      依次执行代码
        遇到var声明赋值语句给调用对象相应的属性赋值
        遇到未声明赋值语句,在全局对象中查找是否已有该属性,如果没有,增加相应的属性,最后赋值
        遇到函数调用,创建嵌套函数的调用对象
          搜索嵌套函数中的var声明和参数,创建嵌套函数的调用对象相应的属性,初始化为 undefined
          创建嵌套函数执行环境,作用域链--第一对象:嵌套函数的调用对象;第二对象:调用                 对象;第三对象:全局对象

我的总结,先创建变量对象,搜索代码,找寻声明的赋值语句(注意是用var声明的赋值语句,未用var声明的赋值语句的属性在执行时才加入到全局对象中),创建执行环境、作用域,依次执行代码。

同时我们还应该注意
第一:在javascript的预解析中,除了对var 变量的预定义,还包括了提取对函数的定义,所以可以在script的任何地方定义函数,在任何地方调用。不限于它之前,而JS还有种函数的定义方式为字面量定义法,如
alert(typeof y3); //结果为undefined
var y3 = function (){ 
  console.log('1'); 
}

javascript 引擎在预解析 var 时 会给他们一个初始值 undefined,这样一来,如果我们在它的声明之前调用它,javascript 引擎还没拿到它的真实值,自然会报"xxx is not a function" 的错。
这就是为什么函数的调用一定要在函数的字面定义法的声明之后的原因了。
第二:javascript 在预解析时function的声明优先级比var的高。
alert(typeof y5);
var y5 = 'angle';
function y5(){
console.log('ghost'); 
}
alert(y5);
/*首先同样的y5,由于function的声明优先级高,所以其弹出的类型为function,但是当第二次alert时,其值已赋值为angle。
*/
分享到:
评论

相关推荐

    浅析JavaScript作用域链、执行上下文与闭包

    JavaScript 采用词法作用域(lexical scoping),函数执行依赖的变量作用域是由函数定义的时候决定,而不是函数执行的时候决定,通过本文给大家介绍JavaScript作用域链、执行上下文与闭包相关知识,感兴趣的朋友一起...

    浅析JavaScript中的变量复制、参数传递和作用域链

    今天学习笔记主要有这样几个关键字:变量、参数传递、执行环境、变量对象、作用域链。  1.变量  变量需要注意的有两点:变量声明和复制变量值。  变量声明肯定大家都很熟悉,在JS中我们都是通过 var 关键字...

    深入浅析Vue全局组件与局部组件的区别

    主要介绍了Vue全局组件与局部组件的区别,通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

    浅析JavaScript预编译和暗示全局变量

    1. 暗示全局变量 未声明的变量称为暗示全局变量。 var a = 1; //函数体外声明的变量称为全局变量 b = 2; // 无论函数体外或函数体内未声明的变量都称为...2. JavaScript执行过程 1. 语法分析,若存在低级语法错误,

    浅析JavaScript声明变量

    使用var关键词声明变量的作用域是当前的执行上下文,有可能是外围函数,或者,当变量声明在函数体之外时,则为全局变量。 定义在函数体外的都属于全局变量,定义在函数体内的属于局部变量。这里的定义是指通过var...

    深化浅析JavaScript中的作用域和上下文_.docx

    深化浅析JavaScript中的作用域和上下文_.docx

    JS变量提升原理与用法实例浅析

    一个例子: (局部变量与全局变量同名时 , 局部变量覆盖全局变量) var a=全局变量; function test() { [removed]ln(a); var a=局部变量; [removed]ln(a); } test(); 上例的两个输出结果是 undefined局部变量 第...

    浅析JavaScript中作用域和作用域链

    本文主要介绍了JavaScript中作用域和作用域链解析,条理分明,方便理解,这里推荐给小伙伴们,有需要的朋友可以参考下

    浅析php变量作用域的一些问题

    昨晚就与到这么一个问题,是全局变量在函数中的问题。今天搜索了一下,发现一篇相当不错的文章,讲了php中的变量作用域。是一位网友翻译的在这贴一下: 变量范围变量的范围即它定义的上下文背景(译者:说白了,也...

    浅析matlab多变量拟合.doc

    浅析matlab多变量拟合.doc

    深入浅析vue全局环境变量和模式

    我们可以在项目根目录中的下列文件来指定环境变量: .env # 在所有的环境中被载入 .env.local # 在所有的环境中被载入,但会被 git 忽略 .env.[mode] # 只在指定的模式中被载入 .env.[mode].local # 只在指定的...

    浅析JavaScript的安全性和执行效率.pdf

    浅析JavaScript的安全性和执行效率.pdf

    深入浅析javascript中的作用域(推荐)

    所谓的作用域,可以简单理解为一个可以读、写的范围(区域),有些js经验的同学可能会说:”js没有块级作用域”,js除了全局作用域外,只有函数可以创建作用域。作用域的一个好处就是可以隔离变量。 我们通过一些例子来...

    浅析Javascript原型继承

    浅析Javascript原型继承,浅析Javascript原型继承

    浅析php中常量,变量的作用域和生存周期

    在PHP脚本中变量主要有:内置超级全局变量,一般的变量,常量,全局变量,静态变量等等,我们在使用它们的时候除了要正确地知道它们的语法以外,更重要的是,我们要知道它们在本质上的区别与联系—即它们的作用域的...

    浅析js封装和作用域

    在编写web软件时,遇到一些可以共用js的情况,于是就想着如何封装js代码。基本需求很简单,其实就是根据不同的情况封装js代码

    深入浅析JavaScript中的作用域和上下文

    javascript中的作用域(scope)和上下文(context)是这门语言的独到之处,这部分归功于他们带来的灵活性。每个函数有不同的变量上下文和作用域。这些概念是javascript中一些强大的设计模式的后盾。然而这也给开发人员...

Global site tag (gtag.js) - Google Analytics