JavaScript作用域与作用域链
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了JavaScript作用域与作用域链,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4804字,纯文字阅读大概需要7分钟。
内容图文
JavaScript作用域
在JavaScript中,变量的作用域有全局作用域和局部作用域两种
1. 全局作用域(Global Scope)
在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:
(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域,例如:
1 var jotaro = "承太郎"; 2 function doSomething() { 3 var joseph = "乔瑟夫"; 4 function innerSay() { 5 console.log(joseph) 6 } 7 innerSay(); 8 } 9 console.log(jotaro) //承太郎 10 console.log(joseph) //error 11 doSomething(); //乔瑟夫 12 innerSay() //error
(2)所有末定义直接赋值的变量自动声明为拥有全局作用域,例如:
1 function doSomething() { 2 var jotaro = "承太郎"; 3 joseph = "乔瑟夫"; 4 console.log(jotaro) 5 } 6 doSomething(); //承太郎 7 console.log(joseph) //乔瑟夫 8 console.log(jotaro) //脚本错误
变量joseph拥有全局作用域,而jotaro在函数外部无法访问到。
(3)所有window对象的属性拥有全局作用域
一般情况下,window对象的内置属性都拥有全局作用域,例如window.name、window.location、window.top等等。
2. 局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所有在一些地方也会看到有人把这种作用域称为函数作用域,例如下列代码中的blogName和函数innerSay都只拥有局部作用域。
1 function doSomething() { 2 var joseph = "乔瑟夫"; 3 function innerSay() { 4 console.log(joseph) 5 } 6 innerSay(); 7 } 8 console.log(joseph) //脚本错误 9 innerSay(); //脚本错误
作用域链(Scope Chain)
1 var name1 = "haha"; 2 function changeName() { 3 var name2 = "xixi"; 4 function swapName() { 5 console.log(name1);//haha 6 console.log(name2);//xixi 7 var tempName = name2; 8 name2 = name1; 9 name1 = tempName; 10 console.log(name1);//xixi 11 console.log(name2);//haha 12 console.log(tempName);//xixi 13 } 14 swapName(); 15 console.log(name1);//haha 16 console.log(name2);//xixi 17 //console.log(tempName); 18 } 19 changeName(); 20 console.log(name1);//xixi 21 //console.log(name2); 抛出错误:Uncaught ReferenceError: name2 is not defined 22 //console.log(tempName);抛出错误:Uncaught ReferenceError: tempName is not defined
上述代码中,一共有三个执行环境:全局环境、changeName()的局部环境和 swapName() 的局部环境。所以,
1.函数 swapName()的作用域链包含三个对象:自己的变量对象----->changeName()局部环境的变量对象 ----->全局环境的变量对象。
2.函数changeName()的作用域包含两个对象:自己的变量对象----->全局环境的变量对象。
就上述程序中出现的变量和函数来讲(不考虑隐形变量):
1.swapName() 局部环境的变量对象中存放变量 tempName;
2.changeName() 局部环境的变量对象中存放变量 name2 和 函数swapName();
3.全局环境的变量对象中存放变量 name1 、函数changeName();
在swapName()的执行环境中,在执行第5句代码时,解析器沿着函数 swapName()的作用域链一级级向后回溯查找变量 name1,直到在全局环境中找到变量 name1.并输出在控制台上。同样,在执行第6句代码时,解析器沿着函数 swapName()的作用域链一级级向后回溯,在函数changeName()的变量对象中发现变量 name2.通过代码对 name1 和 name2进行交换,并输出在控制台上,根据结果我们发现,这两个变量的值确实交换了。因此我们可以得出结论,函数的局部环境可以访问函数作用域中的变量,也可以访问和操作父环境(包含环境)乃至全局环境中的变量。
在changeName() 的执行环境中,执行第15行和第16行代码时,可以正确地输出 name1 和 name2 和两个变量的值(调用了函数swapName(),所以俩变量的值已相互交换),那是因为 name1 在changName()的父环境(全局环境)中, name2 在他自己的局部环境中,即 name1 和 name2 都在其作用域链上。但当执行第17行代码是发生错误 tempName is not defined。因为解析器沿着 函数changeName()的作用域链一级级的查找 变量 tempName时,并不能找到该变量的存在(变量 tempName不在其作用域链上),所以抛出错误。因此,我们可以得出结论:父环境只能访问其包含环境和自己环境中的变量和函数,不能访问其子环境中的变量和函数。
同理,在全局环境中,其变量对象中只存放变量 name1 、函数changeName(); 解析器只能访问变量 name1 和函数 changeName(), 而不能访问和操作 函数 changeName() 和函数 swapName() 中定义的变量或者函数。因此,在执行第21行和第22行代码时抛出变量没有定义的错误。所以说,全局环境只能访问全局环境中的变量和函数,不能直接访问局部环境中的任何数据。
其实,我们可以把作用域链想象成这样(里面的能访问外面的,外面的不能访问里面的,图为参考):
作用域链相关知识的总结:
1.执行环境决定了变量的生命周期,以及哪部分代码可以访问其中变量
2,执行环境有全局执行环境(全局环境)和局部执行环境之分。
3.每次进入一个新的执行环境,都会创建一个用于搜索变量和函数的作用域链
4.函数的局部环境可以访问函数作用域中的变量和函数,也可以访问其父环境,乃至全局环境中的变量和环境。
5.全局环境只能访问全局环境中定义的变量和函数,不能直接访问局部环境中的任何数据。
6.变量的执行环境有助于确定应该合适释放内存。
引用文章:https://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html
:https://www.cnblogs.com/buchongming/p/5858026.html
内容总结
以上是互联网集市为您收集整理的JavaScript作用域与作用域链全部内容,希望文章能够帮你解决JavaScript作用域与作用域链所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。