首页 >> js开发 >> js代码JavaScript进阶(二)词法作用域与作用域链实例分析
js代码JavaScript进阶(二)词法作用域与作用域链实例分析
发布时间: 2021年1月13日 | 浏览:
| 分类:js开发
本文实例讲述了JavaScript词法作用域与作用域链。分享给大家供大家参考,具体如下:一、作用域域表示的就是范围,即作用域,就是一个名字在什么地方可以使用,什么时候不能使用。想了解关于作用域的问题推荐阅读《你不知道的JavaScript上卷》第一章(或第一部分),从编译原理的角度说明什么是作用域。概括的说作用域就是一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量。1.1 块级作用域在C、Java、C#等编程语言中,下面的语法报错(伪代码)
{
var num = 123;
{
console.log( num );
// num => 123
}
}
console.log( num );
//报错
{
var num = 123;
{
console.log( num );
// num => 123
}
}
console.log( num );
//报错1.2 JS的词法作用域所谓的词法(代码)作用域,就是代码在编写过程中体现出来的作用范围,代码一旦写好,不用执行,作用范围就已经确定好了,这个就是所谓的词法作用域。在JS中词法作用域的规则:
函数允许访问函数外部的数据
整个代码结构中只有函数可以限定作用域
作用规则首先使用提升规则分析
如果当前作用域中有了名字了,就不考虑外面的名字
函数允许访问函数外部的数据整个代码结构中只有函数可以限定作用域作用规则首先使用提升规则分析如果当前作用域中有了名字了,就不考虑外面的名字例子1:
var num = 123;
function foo(){
console.log( num );
}
foo();
//123
var num = 123;
function foo(){
console.log( num );
}
foo();
//123例子2:
if( false ){
var num = 123;
}
console.log( num ); //undefined
if( false ){
var num = 123;
}
console.log( num ); //undefined例子3:
var num = 123;
function foo () {
var num = 456;
function func(){
console.log( num );
}
func();
}
foo();
//456
var num = 123;
function foo () {
var num = 456;
function func(){
console.log( num );
}
func();
}
foo();
//456二、作用域链只有函数才能制造作用域结构,那么只要是代码,至少有一个作用域,即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域,那么将这样的所有作用域列出来,可以有一个结构:函数内指向函数外的链式结构例如:
function f1() {
function f2() {
}
}
var num = 456;
function f3() {
function f4() {
}
}
function f1() {
function f2() {
}
}
var num = 456;
function f3() {
function f4() {
}
}作用域链结构与DOM树结构很相似.2.1 绘制作用域链步骤:
看整个全局是一条链,即顶级链,记为0级链
看全局作用域中有什么成员声明,就以方格的形式绘制到0级链上
再找函数,只有函数可以限制作用域,因此从函数中引出新链,标记为1级链
然后在每一个1级链中再次往复刚才的行为
看整个全局是一条链,即顶级链,记为0级链看全局作用域中有什么成员声明,就以方格的形式绘制到0级链上再找函数,只有函数可以限制作用域,因此从函数中引出新链,标记为1级链然后在每一个1级链中再次往复刚才的行为2.2 变量的访问(搜索)规则
首先看变量在第几条链上,在该链上看是否有变量的定义与赋值,如果有直接使用
如果没有到上一级链上找( n - 1 级链),如果有直接使用,停止继续查找。
如果还没有在此往上找… 直到全局链(0级),还没有就是is not defined
注意,切记:同级的链不可混合查找
首先看变量在第几条链上,在该链上看是否有变量的定义与赋值,如果有直接使用如果没有到上一级链上找( n - 1 级链),如果有直接使用,停止继续查找。如果还没有在此往上找… 直到全局链(0级),还没有就是is not defined注意,切记:同级的链不可混合查找绘制如下程序的作用域链
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();
//123
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();
//123函数f1 和变量 num=456, 在0级链,而f1下又可以展开1级链,1级链上有num=123和函数f2。程序f1()调用进入左边1级链,而f1中又调用了f2函数,f2函数中console.log(num)可以看作在2级链,此时,程序会向这一条链向上查找,首先2级链没有num,向上到达1级链,刚好1级链上有num=123,所以就直接使用123,程序最后的结果就是打印123.console.log(num)2.3 如何分析代码
在分析代码的时候切记从代码的运行角度上来分析,如果代码给变量赋值了,一定要标记到图中
如果代码比较复杂,可以在图中表示代码的内容,有时候还要将原型图与作用域图结合起来分析
在分析代码的时候切记从代码的运行角度上来分析,如果代码给变量赋值了,一定要标记到图中如果代码比较复杂,可以在图中表示代码的内容,有时候还要将原型图与作用域图结合起来分析分析如下代码:
var num = 123;
function f1() {
console.log( num );
}
function f2(){
var num = 456;
f1();
}
f2();
//123
var num = 123;
function f1() {
console.log( num );
}
function f2(){
var num = 456;
f1();
}
f2();
//123作用域链图:首先把num=123,函数f1,函数f2画在0级链上。f1中只有一句console,画出一条1级链,f2也下画出1级链,链上有num=456和函数调用语句f1();调用f2(),进入f2函数的作用域链,而在f2中又调用了f1函数,程序进入f1的作用域链,所以console.log(num)会在此链上查找是否存在num,没有,继续向上一级链查找,刚好在0级链上找到了num=123,所以f1函数中的console.log(num)就是123.console.log(num)console.log(num)感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools./code/HtmlJsRun测试上述代码运行效果。在线HTML/CSS/JavaScript代码运行工具在线HTML/CSS/JavaScript代码运行工具http://tools./code/HtmlJsRun关于JavaScript相关内容可查看本站专题:《JavaScript常用函数技巧汇总》、《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》及《JavaScript数学运算用法总结》JavaScript常用函数技巧汇总javascript面向对象入门教程JavaScript错误与调试技巧总结JavaScript数据结构与算法技巧总结JavaScript数学运算用法总结希望本文所述对大家JavaScript程序设计有所帮助。
{
var num = 123;
{
console.log( num );
// num => 123
}
}
console.log( num );
//报错
{
var num = 123;
{
console.log( num );
// num => 123
}
}
console.log( num );
//报错1.2 JS的词法作用域所谓的词法(代码)作用域,就是代码在编写过程中体现出来的作用范围,代码一旦写好,不用执行,作用范围就已经确定好了,这个就是所谓的词法作用域。在JS中词法作用域的规则:
函数允许访问函数外部的数据
整个代码结构中只有函数可以限定作用域
作用规则首先使用提升规则分析
如果当前作用域中有了名字了,就不考虑外面的名字
函数允许访问函数外部的数据整个代码结构中只有函数可以限定作用域作用规则首先使用提升规则分析如果当前作用域中有了名字了,就不考虑外面的名字例子1:
var num = 123;
function foo(){
console.log( num );
}
foo();
//123
var num = 123;
function foo(){
console.log( num );
}
foo();
//123例子2:
if( false ){
var num = 123;
}
console.log( num ); //undefined
if( false ){
var num = 123;
}
console.log( num ); //undefined例子3:
var num = 123;
function foo () {
var num = 456;
function func(){
console.log( num );
}
func();
}
foo();
//456
var num = 123;
function foo () {
var num = 456;
function func(){
console.log( num );
}
func();
}
foo();
//456二、作用域链只有函数才能制造作用域结构,那么只要是代码,至少有一个作用域,即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域,那么将这样的所有作用域列出来,可以有一个结构:函数内指向函数外的链式结构例如:
function f1() {
function f2() {
}
}
var num = 456;
function f3() {
function f4() {
}
}
function f1() {
function f2() {
}
}
var num = 456;
function f3() {
function f4() {
}
}作用域链结构与DOM树结构很相似.2.1 绘制作用域链步骤:
看整个全局是一条链,即顶级链,记为0级链
看全局作用域中有什么成员声明,就以方格的形式绘制到0级链上
再找函数,只有函数可以限制作用域,因此从函数中引出新链,标记为1级链
然后在每一个1级链中再次往复刚才的行为
看整个全局是一条链,即顶级链,记为0级链看全局作用域中有什么成员声明,就以方格的形式绘制到0级链上再找函数,只有函数可以限制作用域,因此从函数中引出新链,标记为1级链然后在每一个1级链中再次往复刚才的行为2.2 变量的访问(搜索)规则
首先看变量在第几条链上,在该链上看是否有变量的定义与赋值,如果有直接使用
如果没有到上一级链上找( n - 1 级链),如果有直接使用,停止继续查找。
如果还没有在此往上找… 直到全局链(0级),还没有就是is not defined
注意,切记:同级的链不可混合查找
首先看变量在第几条链上,在该链上看是否有变量的定义与赋值,如果有直接使用如果没有到上一级链上找( n - 1 级链),如果有直接使用,停止继续查找。如果还没有在此往上找… 直到全局链(0级),还没有就是is not defined注意,切记:同级的链不可混合查找绘制如下程序的作用域链
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();
//123
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();
//123函数f1 和变量 num=456, 在0级链,而f1下又可以展开1级链,1级链上有num=123和函数f2。程序f1()调用进入左边1级链,而f1中又调用了f2函数,f2函数中console.log(num)可以看作在2级链,此时,程序会向这一条链向上查找,首先2级链没有num,向上到达1级链,刚好1级链上有num=123,所以就直接使用123,程序最后的结果就是打印123.console.log(num)2.3 如何分析代码
在分析代码的时候切记从代码的运行角度上来分析,如果代码给变量赋值了,一定要标记到图中
如果代码比较复杂,可以在图中表示代码的内容,有时候还要将原型图与作用域图结合起来分析
在分析代码的时候切记从代码的运行角度上来分析,如果代码给变量赋值了,一定要标记到图中如果代码比较复杂,可以在图中表示代码的内容,有时候还要将原型图与作用域图结合起来分析分析如下代码:
var num = 123;
function f1() {
console.log( num );
}
function f2(){
var num = 456;
f1();
}
f2();
//123
var num = 123;
function f1() {
console.log( num );
}
function f2(){
var num = 456;
f1();
}
f2();
//123作用域链图:首先把num=123,函数f1,函数f2画在0级链上。f1中只有一句console,画出一条1级链,f2也下画出1级链,链上有num=456和函数调用语句f1();调用f2(),进入f2函数的作用域链,而在f2中又调用了f1函数,程序进入f1的作用域链,所以console.log(num)会在此链上查找是否存在num,没有,继续向上一级链查找,刚好在0级链上找到了num=123,所以f1函数中的console.log(num)就是123.console.log(num)console.log(num)感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools./code/HtmlJsRun测试上述代码运行效果。在线HTML/CSS/JavaScript代码运行工具在线HTML/CSS/JavaScript代码运行工具http://tools./code/HtmlJsRun关于JavaScript相关内容可查看本站专题:《JavaScript常用函数技巧汇总》、《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》及《JavaScript数学运算用法总结》JavaScript常用函数技巧汇总javascript面向对象入门教程JavaScript错误与调试技巧总结JavaScript数据结构与算法技巧总结JavaScript数学运算用法总结希望本文所述对大家JavaScript程序设计有所帮助。
相关文章:
- jsElement Breadcrumb 面包屑的使用方法js大全
- js使用React-Router实现前端路由鉴权的示例代码js大全
- JavaScriptthree.js欧拉角和四元数的使用方法
- js关于angular浏览器兼容性问题的解决方案js大全
- jsElement Input输入框的使用方法js大全
- jsvue项目使用$router.go(-1)返回时刷新原来的界面操作js大全
- jsvue 页面回退mounted函数不执行的解决方案js大全
- js解决vuex数据页面刷新后初始化操作js大全
- js代码详解JavaScript自定义函数
- js解决vue动态路由异步加载import组件,加载不到module的问题js大全