JavaScript 作用域分析总结

发布于 2024-04-08 12:39:57 字数 5316 浏览 26 评论 0

一、JS 解析顺序和作用域

解析顺序:

  • 定义(先找 var function
  • 执行 ( 在逐步执行 )
  • 注意:如果函数名和 var 定义的变量相同, var 会被函数覆盖

作用域:

  • 每个 script 是一个作用域
  • 每个函数 {} 是一个作用域
  • 程序每执行到一个作用域,都是按照解析顺序解析代码;
  • 作用域链:从内往外找要找函数内的变量;

二、案例分析


分析前请记住这段话

解析顺序:

  • 定义(先找 var function
  • 执行 ( 在逐步执行 )
  • 注意:如果函数名和 var 定义的变量相同, var 会被函数覆盖

举例 1

alert( a );
var a = 10;
alert( a );
function a(){alert(20)};
alert( a );
var a = 30;
alert( a );
function a(){alert(40)};
alert( a );
// 函数块 10 10 30 30

分析

  • 找定义 function a(){alert(40)};
  • 执行 alert( a ) // 函数块
a = 10;
alert( a ); // 10
alert( a ); // 10
a = 30;
alert( a ); // 30
alert( a ); // 30

举例 2

a();
var a = function(){alert( 1 );}
a();
function a(){alert(2);}
a();
var a = function(){alert(3);}
a();
//2 1 1 3

分析

找定义

function a(){alert(2);}

执行

a(); // 2
a = function(){alert( 1 );}
a(); // 1
a(); // 1
a = function b(){alert(3);};
a(); // 3

举例 3

 var a = 0;
  function fn(){
           alert( a );
           var a = 1;
           alert( a );
    }
 alert(a);
fn();

分析

找定义

var afunction fn(){}

执行

a = 0;fn(); ===> 1:找定义
2:执行 alert(a); // undefined
a = 1;
alert(a); //1

举例 4

fn()();
var a = 0;
function fn(){
alert( a );
var a = 3;
function c(){
alert( a );
}
return c;
};

分析

找定义

var afunction fn

执行

fn() ===> 1:找定义 function c
2:执行 alert(a); //undefined
a = 3
return function cfn()() ==>1:找定义 function c
2:alert(a); // undefined 3a = 0;

举例 5

var a = 5;
function fn(){
var a = 10;
alert(a);
function b(){
a++;
alert(a);
};
return b;
};
var c = fn();
c();
fn()();
c();

分析

找定义 var a

function fnvar c

执行 a = 5;

c = fn();
=== > 1:找定义 var a
function b
2:执行 a = 10;
alert(a); //10
return function b(){};c();
=========> 1:找定义
2:执行 a++; //11
alert(a);//11
fn()(); //10 11c()
========> 1:找定义
2:执行 a++;//11+1;
alert(a); //12

举例 6

//alert(x); //9:执行弹出 x,结果 x 没定义,错误.
alert(i); //9:执行弹出 i,然而 i 之前已经定义,只不过没地址,因此是 undefiend
var i = 10; //1:var i;    10:把常量池中 10 的地址赋给栈中的 i
var j = "你好"; //2:var j;   11:把常量池中 你好 的地址复给栈中的 j
var k = z = null; //3:var k,z;  12:把堆中 null 的地址赋值给 z 和 k
var m = function(){ //4:var m;   5:function 匿名函数  13:把匿名函数在堆中的地址赋给栈中的 m
    alert(2);
}
var b = document.body;//6:var b;    14:把堆中 document.body 对象的地址赋给栈中的 b
var f = true; //7:var f; 15:把常量池中 true 的地址赋给栈中的变量 f
function m(){ //8:function m;
    alert(1);
}

举例 7

function m(){
    c = 50;//在局部变量中找不到定义的 c 沿着作用域链找到了全局变量的 c
    alert('哈哈哈');
    //var c;
}

var c = 150; // 函数 m() 还未执行到 还没被销毁 此时全局 c 的值 c=50
m();
var c = 20; // 到这里一步 m() 已经执行完了 函数已经销毁了  这里的 c 还是 20
alert(c); //20

举例 8

function m(){
    c = 50;//在局部变量中找不到定义的 c 沿着作用域链找到了全局变量的 c
    alert('哈哈哈');
    function inner(){
        c = 30;
        alert('嘻嘻');
    }
    inner(); // c 在函数内部找不到定义 所以沿着作用域链找到了全局的 c
}

var c = 20; // 到这里一步 m() 还没执行 函数没被销毁  这里的 c 是 30
m();

alert(c); // 30

三、闭包


3.1 概念


  • 其实是函数嵌套函数
  • 每个函数都是一个独立的作用域
  • 每个都有自己的生命周期
  • 延长局部变量的生命周期

3.2 例子


<ul id="list">
  <li>01</li>
  <li>02</li>
  <li>03</li>
  <li>04</li>
</ul>
var liDoms = document.getElementById("list").getElementsByTagName("li");
for(var i=0;i<liDoms.length;i++){
   (function(a){
       liDoms[a].onclick = function(){
           alert(a);
       }
   })(i)
}
// 函数也是一种数据类型 它和 number string boolean object 特殊在可以打括号去执行它

// 函数中的循环
function test(){
    var arr = [],i;
    for(i=0;i<3;i++){
        // arr[i] = (function fn(a){
        //     return a;
        // })(i);

        arr[i] = fn(i);
    }
    return arr;
}


function fn(a){
    return a;
}

var c = test();
//alert(c);
for(var i=0;i<c.length;i++){
    var value = c[i];
    alert(value);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

回心转意

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

我们的影子

文章 0 评论 0

素年丶

文章 0 评论 0

南笙

文章 0 评论 0

18215568913

文章 0 评论 0

qq_xk7Ean

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文