• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

JS05-作用域

相关文章 海叔叔 4年前 (2021-11-11) 28次浏览 已收录 0个评论
文章目录[隐藏]

一. 作用域

1. 函数能封闭主定义域

一个变量如果定义在了一个function里面,那么这个变量就是一个局部变量,只在这个function里面有定义。出了这个function,就如同没有定义过一样。

function fn(){
    var a = 3;    //定义在一个函数里面的变量,局部变量,只有在函数里面有定义
    console.log("我是函数里面的语句,所以我知道a值是" + a);
}
fn();
console.log("我是函数外面的语句,我认为a的值是" + a);

a被var在了function里面,所以现在这个a变量只在函数内定义

JavaScript变量作用域非常的简单,没有块级作用域,管理住作用域的只有一个东西:函数。

如果一个变量,没有定义在任何的function中,那么它将在全部程序范围内都有定义:

就是你在js的任何位置都能够使用它

var a = 10;    //定义在全局范围内的一个变量,全局变量,在程序任何一个角落都有定义
function fn(){
    console.log("我是函数里面的语句,我认识全局变量a,他的值为" + a);
}
fn();
console.log("函数外面的语句,我也也认识a,它的值为" + a)

总结:

1、定义在function里面的变量,叫做局部变量,只在function里面有定义,出了function没有定义的。
2、定义在全局范围内的,没写在任何function里面的,叫做全局变量,全局都都认识。

2. 作用域链

当遇见一个变量时,JS引擎会从其所在的作用域依次向外层查找,查找会在找到第一个匹配的标识符的时候停止.

function outer(){
    var a = 3;        //a的作用域就是outer
    function inner(){
        var b = 5;        //b的作用域就是inner
        console.log(a);    //能够正常输出3,a在本层没有定义,就是找上层
        console.log(b);   //能够正常输出5
    }
    inner();
}
outer();
console.log(a);        //报错,因为a的作用域outer

多层嵌套,如果有同名的变量,那么就会发生“遮蔽效应”:

var a = 2;        //全局变量
function fn(){
    var a = 3;         //就把外层的a给遮蔽了,这函数内部看不见外层的a了。
    console.log(a);    //输出3,变量在当前作用域寻找,找到了a的定义值为5
}
fn();
console.log(a);  //输出2,变量在当前作用域寻找,找到了a的定义值为1

作用域链:一个变量在使用的时候,就会在当前层去寻找它是否被定义,如果找不到,就找上一层function,直到找到全局变量,如果全局也没有,就报错。

var a = 1;        //全局变量
var b = 2;        //全局变量
function outer(){
    var a = 3;        //遮蔽了外层的a,a局部变量
    function inner(){
        var b = 4;  //遮蔽了外层的b,b局部变量
        console.log(a);   //① 输出3,a现在在当前层找不到定义的,所以就上一层寻找
        console.log(b);   //② 输出4
    }
    inner();        //调用函数
    console.log(a);    //③ 输出3
    console.log(b); //④ 输出2 b现在在当前层找不到定义的,所以就上一层寻找
}
outer();        //执行函数,控制权交给了outer
console.log(a);    // ⑤ 输出1
console.log(b); // ⑥ 输出2

3. 不写var就自动成全局变量了

// var a, 相当于在全局var了一个a
function fn(){
    a = 3;        //这个a第一次赋值的时候,并没有var过,
    //所以就自动的在全局的范围帮你var了一次
}
fn();
console.log(a);

这是JS的一个机理,如果遇见了一个标识符,从来没有var过,并且还赋值了:

num = 12;
那么就会自动帮你在全局范围内定义var num;

告诉我们一个道理,变量要老老实实写var。

4.函数的参数,会默认定义为这个函数的局部变量

function fn(a,b,c,d){
    // var a,b,c,d; 相当于在函数内部var四个变量,是局部变量
}

a,b,c,d就是一个fn内部的局部变量,出了fn就没有定义。

5.全局变量的作用

5.1 通信,共同操作同一个变量

两个函数同时操作同一个变量,一个增加,一个减少,函数和函数通信。

var num = 0;
function add(){
    num++;
}
function remove(){
    num--;
}

5.2 累加,重复调用函数的时候,不会重置

var num = 0;
function baoshu(){
    num++;
    console.log(num);
}
baoshu();    //1
baoshu();    //2
baoshu();    //3

如果num定义在baoshu里面,每次执行函数就会把num重置为0:

function baoshu(){
    var num = 0;
    num++;
    console.log(num);
}
baoshu();    //1
baoshu();    //1
baoshu();    //1

6.函数的定义也有作用域

//这个函数返回a的平方加b的平方
function pingfanghe(a,b){
    return  pingfang(a) + pingfang(b);
    //返回m的平方
    function pingfang(m){
        return Math.pow(m,2)
    }
}

// 现在相求4的平方,想输出16
pingfang(4); //报错,因为全局作用域下,没有一个函数叫做pingfang
机理:

function big{

function small{
​ }

​ small(); //可以运行

}

small();

//不能运行,因为小函数定义在了大函数里面,离开大函数没有作用域。

二. 闭包

1. 闭包

function outer(){
    var a = 33;
    function inner(){
        console.log(a);
    }
    return inner;
}
var inn = outer();
inn(); //弹出333

推导过程:

我们之前已经学习过,inner()这个函数不能在outer外面调用,因为outer外面没有inner的定义:

function outer(){
    var a = 888;
    function inner(){
        console.log(a);
    }
}
//在全局调用inner但是全局没有inner的定义,所以报错
inner();

但是我们现在就想在全局作用域下,运行outer内部的inner,此时我们必须想一些奇奇怪怪的方法。

有一个简单可行的办法,就是让outer自己return掉inner:

function outer(){
    var a = 33;
    function inner(){
        console.log(a);
    }
    return inner;    //outer返回了inner的引用
}
var inn = outer();    //inn就是inner函数了
inn();            //执行inn,全局作用域下没有a的定义
//但是函数闭包,能够把定义函数的时候的作用域一起记忆住
//能够输出333

这就说明了,inner函数能够持久保存自己定义时的所处环境,并且即使自己在其他的环境被调用的时候,依然可以访问自己定义时所处环境的值。

一个函数可以把它自己内部的语句,和自己声明时所处的作用域一起封装成了一个密闭环境,我们称为“闭包” (Closures)。

每个函数都是闭包,每个函数天生都能够记忆自己定义时所处的作用域环境。但是,我们必须将这个函数,挪到别的作用域,才能更好的观察闭包。这样才能实验它有没有把作用域给“记住”。

因为我们总喜欢在函数定义的环境中运行函数。从来不会把函数往外挪。那为啥学习闭包,防止一些隐患,。

2.闭包的性质

每次重新引用函数的时候,闭包是全新的。

function outer(){
    var count = 0;
    function inner(){
        count++;
        console.log(count);
    }
    return inner;
}
var inn1 = outer();
var inn2 = outer();
inn1();    //1
inn1();    //2 
inn1(); //3
inn1(); //4
inn2(); //1
inn2(); //2
inn1(); //5

无论它在何处被调用,它总是能访问它定义时所处作用域中的全部变量


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:JS05-作用域

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址