博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
变量作用域和作用域链
阅读量:6903 次
发布时间:2019-06-27

本文共 2209 字,大约阅读时间需要 7 分钟。

变量作用域

一个变量的作用域是程序源代码中定义这个变量的区域。全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义的。然而在函数内声明的变量只在函数体内有定义。

在函数体内,局部变量的优先级高于全局变量。如果在函数体内声明一个局部变量或者函数参数中带有的变量和全局变量重名,那么全局变量会被局部变量覆盖。

var scope = "global scope"                  // 声明全局变量   function checkscope() {     var scope = "local scope";             // 声明同名局部变量     function f() {       return scope;                        // 返回局部变量的值     }     return f()   }   checkscope()复制代码

函数定义是可以嵌套的。由于每个函数都有自己的作用域,因此会出现几个局部作用域的嵌套情况。

var scope = "global scope"                      // 全局变量    function checkscope() {      var scope = "local scope";                // 局部变量      function nested() {        var scope = "nested scoped"             // 嵌套作用域内的局部变量        return scope;                           // 返回当前作用域内的值      }               return nested()    }   checkscope()复制代码

作用域链

如果将一个局部变量看做是自定义实现的对象的属性的话,那么可以换个角度来解读变量作用域。每段JavaScript代码(全局代码或者函数)都有一个与之关联的作用域链。

作用域链的理解

这个作用域链是一个对象列表或链表,这组对象定义了这段代码“作用域中”的变量。当JavaScript需要查找变量x的值的时候(这个过程叫做变量解析),它会从链中的第一个对象开始查找,如果这个对象中有一个名为x的属性,则会直接使用这个属性的值;如果第一个对象没有这个名为x的属性,它会查找链上的下一个对象,以此类推。。。 如果作用域链上没有任何一个对象含有属性x,则认为改代码的作用链上不存在x,并最终抛出一个引用错误异常(ReferenceError)。

作用域链的组成

在JavaScript的最顶层代码中(不包含在任何函数定义内的代码),作用域链有一个全局对象组成。在不包含嵌套的函数体内,作用域上有两个对象,第一个是定义函数参数和局部变量的对象,第二个是全局对象。在一个嵌套函数体内,作用域链上至少有三个对象。

理解对象链的创建规则: 当定义一个函数时,它实际上保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将找个对象添加至保存的那个作用域链上,同时创建一个新的更长的表示函数调用作用域的“链”。

扩展:

with语句

with语句用于临时扩展作用域链

它具有如下的语法:

with(object)statement复制代码

这条语句将object添加到作用域链的头部,然后执行statement,最后把作用域链恢复到原始状态。

在对象嵌套层次很深的时候通常会使用with语句来简化代码编写。
例如,在客户端JavaScript中,可能会使用类似下面这种表达式来访问一个HTML表单中的元素:

document.forms[0].address.value复制代码

如果这种表达式在代码中多次出现,则可以使用with语句将form对象添加至作用域链的顶层:

with(document.forms[0]){    // 直接访问表单元素,例如:    name.value = "";    address.value = "";    email.value = "";}复制代码

这种方法减少了大量的输入,不用再为每个属性名添加document.forms[0]前缀。这个对象临时挂载在作用域链上,当JavaScript需要解析诸如address的标识符时,就会自动在这个对象中查找。当然,不使用with语句的等价代码可以写成这样

var f = document.forms[0];f.name.value = "";f.address.value = "";f.email.value = "";复制代码

不要忘记,只有在查找标识符的时候才会用到作用域链,创建新的变量的时候不使用它,看一下下面这行代码:

with(o)x = 1; 如果对象o有一个属性x,那么这行代码给这个属性赋值为1。但如果o中没有定义属性x,这段代码和不使用with语句的代码x=1是一模一样的。它给一个局部变量或者全局变量x赋值,或者创建全局对象的一个新属性。with语句提供了一种读取o的属性的快捷方式,但它并不能创建o的属性。

上一篇: 你不知道的javascript—作用域、闭包

查看原文

转载地址:http://mhvdl.baihongyu.com/

你可能感兴趣的文章
python-玉米(小米)商城作业
查看>>
Eclipse调试DEBUG时快速查看某个变量的值的快捷键
查看>>
记录未预编译文件“*.aspx”,因此不能请求该文件的几种处理办法
查看>>
一个朋友
查看>>
webservice(pers)
查看>>
[转载]安装archlinux 以后没有 ifconfig,route ,nslo
查看>>
人见人爱A^B
查看>>
zoj 3795 Grouping tarjan缩点 + DGA上的最长路
查看>>
浏览器内核
查看>>
zabbix-server安装部署配置
查看>>
终于解决 xUnit.net 测试中无法输出到控制台的问题
查看>>
【素数筛】分解质因数
查看>>
【ADT】队列的基本C语言实现
查看>>
NYOJ-1057 寻找最大数(三)(贪心)
查看>>
【转】 [UnityUI]UGUI射线检测
查看>>
应用被强杀了怎么办
查看>>
jquery validate 插件使用心得
查看>>
Windows下安装mysql后,不知道root密码,如果修改root密码
查看>>
Linuxドライバ_LDD3メモ_ハードウェアとの通信
查看>>
数学之美系列四 -- 怎样度量信息?
查看>>