三分钟带你深刻理解 JavaScript 的函数做用域

什么是做用域 ?

做用域:一个变量能够生效的范围。浏览器

变量不是在全部地方均可以使用的,而这个变量的使用范围就是咱们要说的做用域。markdown

注意:在JavaScript中,划分做用域也是用大括号划分的, 可是在 JS 之中可以有效限定做用域的大括号只有函数大括号!函数

有哪些做用域 ?

全局做用域(再也不任何函数内)

学习使用做用域,如下内容是所须要了解的:学习

  • 全局做用域是最大的做用域
  • 在全局做用域中定义的变量能够在任何地方使用
  • 页面打开的时候,浏览器会自动给咱们生成一个全局做用域 window
  • 这个全局做用域会一直存在,直到页面关闭才会销毁

请看下面示例代码:ui

var a = 10;
console.log(a);  // 输出结果: 10
function foo(){
    console.log(a);  // 输出结果: 10
}
foo()
复制代码

当变量 a 声明时,没有被函数大括号包裹, 那么这个变量咱们称之为 全局变量spa

这个全局变量在任何地方均可以访问。设计

局部做用域(在函数内部)

一样的,如下内容也是所须要了解的:code

  • 局部做用域就是在全局做用域下面开辟出来的一个相对小一些的做用域
  • 在局部做用域中定义的变量只能在这个局部做用域内部使用
  • 在 JS 中只有函数能生成一个局部做用域,别的都不行
  • 每个函数,都是一个局部做用域

请看下面示例代码:orm

function foo(){
    var a = 10; //在大括号之中声明的变量只能在这个大括号之中使用;
    console.log(a); // 输出结果: 10
}
foo();
console.log(a); // 报错 => ReferenceError: a is not defined
复制代码

经过上面示例代码能够看出:生命周期

在函数大括号之中声明的变量,这种变量咱们称之为 局部变量

局部变量只能在声明它的做用域之中使用;

咱们见惯了常规状况,如今看一个特殊状况:

声明变量时不使用 var 关键字声明:

注意!这是一个不规范的声明方式!不要使用!不要使用!不用使用!

使用以后致使的结果就是:一个局部变量的声明,在全局中也能够被访问了!( 这样的声明叫作 伪全局变量

请看下面示例代码:

function foo(){
    a = 10; // 此时声明变量 a 没有使用var关键字声明
    console.log(a); // 输出结果:10
}
foo();
console.log(a); // 不报错了,输出结果:10;
复制代码

看完上面的代码示例,你是否是以为这不挺好的嘛,变量 a 能够随便使用,都不用报错了,为何不让使用??

呵呵,别高兴太早,继续往下看,你的这个想法很危险的!

当把局部变量变成伪全局变量:

你会发现:

  1. 生命周期变长,形成必定的负面影响;
  2. 占据了全局命名空间,形成不可预知的错误

是否是脑子里忽然蹦出了好多问题:生命周期是什么鬼?命名空间又是什么鬼??

好吧,上面这个内容我说早了,那么接着往下看:

全局变量和局部变量的区别:

在这里就来聊一下上面的生命周期和命名空间吧!

生命周期(这个变量在内存之中存活的时间)

就是你啥时候能够访问!

  • 全局变量:生命周期是和程序同步的, 程序不关闭,变量就一直存在

    致使的结果就是会让程序变得更重! 若是可能,仍是少设计一点全局变量吧!对你们都好

  • 局部变量:生命周期是和函数执行同步的,函数执行结束变量就被删除了

如今知道啥是生命周期了吧,全局变量多了,可能真的会影响到咱们程序的运行效率,上面说的伪全局变量就是这个道理。

咱们看完了生命周期,再来一块儿看一下命名空间吧!

命名空间(变量名命名的惟一性)

  • 全局变量:命名空间是惟一的,一个页面只有一个

咱们先来举一个小例子,话很少说上代码:

var count = 10;
function foo(){
    // 个人代码 : 个人私人领域;
    // 程序的懒惰原则:函数的大括号之中若是已经有了查找结果,那么就不会继续再查找了;
    // 就近原则;
    var count = 0;
    console.log(count);  // 运行结果:0
}
foo();
console.log(count);  // 运行结果:10
复制代码

为了解决全局之中的命名空间是惟一的这个问题,咱们能够把这个变量放在局部,那么就不会占用全局的命名空间了。

  • 局部变量:命名空间一个做用域一个

    能够用匿名函数来解决命名空间的问题

最后一个问题:我如今要写一大坨代码,和别人的代码要配合 。 这个时候咋写呢???

我能够把代码写在一个没有名字的函数之中! 什么?这样写直接报错 ?
JS 为啥阻止他 ? 若是我当即调用呢!来一个瞒天过海如何?

让匿名函数经历一次运算: 若是函数发生了特定的运算, 那么这个函数就会被当作一个地址;

// 让匿名函数经历一次运算: 若是函数发生了特定的运算,那么这个函数就会被当作一个地址;
    var res = 1 + function(){} 
    console.log(res); // 运行结果:1function(){}
    
    // 利用这个机制使用匿名函数当即调用: 
    +function(){
        console.log("hello world")
    }();
    
    // 函数通过运算变成了地址,被后面的调用运算符调用了;
    !function(){
        console.log("hello world")
    }();

    // 一种广泛的写法 :
        
    (function(){
        console.log("hello world1");
    })()
    // 可能存在的bug;
    (function(){
        console.log("hello world1");
    })();  
    
    // 解决方案:两个匿名函数同时是使用必定要加上分号
    (function(){
        console.log("hello world2");
    })();
    
    // 最终建议写法:
     ;(function(){
         console.log("hello world1");
     })();  
复制代码

最后的最后,再来个总结吧!

一、全局变量不能访问局部变量

二、局部变量能够拿到全局变量


喜欢的朋友欢迎点赞关注,欢迎评论区留言互动。

相关文章
相关标签/搜索