什么是作用域 ?

作用域:一个变量可以生效的范围。 变量不是在所有地方都可以使用的,而这个变量的使用范围就是我们要说的作用域。

注意:在JavaScript中,划分作用域也是用大括号划分的, 但是在 JS 之中能够有效限定作用域的大括号只有函数大括号!

有哪些作用域 ?

- 全局作用域(不再任何函数内)

学习使用作用域,以下内容是所需要了解的:

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

请看下面示例代码:

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

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

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

- 局部作用域(在函数内部)

同样的,以下内容也是所需要了解的:

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

请看下面示例代码:

     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); //
}
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");
})();

最后来个总结吧!

1、全局不能访问局部

2、局部可以拿到全局


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

深入理解JavaScript的函数作用域的更多相关文章

  1. 深入理解 JavaScript 变量的作用域和作用域链

    一个变量的作用域(scope)是程序源代码中定义这个变量的区域.简单的说,作用域就是变量与函数的可访问范围.全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义.局部变量是在函数体内 ...

  2. javascript篇-----函数作用域,函数作用域链和声明提前

    在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于 ...

  3. 理解javascript 回调函数

    ##回调函数定义 百度百科:回调函数 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不 ...

  4. 深入理解JavaScript中的作用域和上下文

    介绍 JavaScript中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,我会尽我所能用最简单的方式来解释作用域.理解作用域将使你的代码脱颖而出,减 ...

  5. JavaScript之函数作用域

    有过类似C语言编程经验的同学应该都知道“块级作用域(block scope)”:花括号内的每一段代码都具有各自的作用域,而且在声明它们的代码段之外是不可见的.而在JavaScript中是没有块级作用域 ...

  6. 谈谈javascript的函数作用域

    在一些类似c语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明他们的代码段之外是不可见的,我们称为块级作用域(block scope),而javascript中没有块级作用域.取 ...

  7. 理解 JavaScript 回调函数并使用

    JavaScript中,函数是一等(first-class)对象:也就是说,函数是 Object 类型并且可以像其他一等对象(String,Array,Number等)一样使用.它们可以"保 ...

  8. 理解JavaScript中的作用域和上下文

    JavaScript对于作用域(Scope)和上下文(Context)的实现是这门语言的一个非常独到的地方,部分归功于其独特的灵活性. 函数可以接收不同的的上下文和作用域.这些概念为JavaScrip ...

  9. 深入理解JavaScript中的作用域、作用域链和闭包

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qappleh/article/detai ...

随机推荐

  1. 吴裕雄--天生自然 PYTHON3开发学习:MySQL - mysql-connector 驱动

    import mysql.connector mydb = mysql.connector.connect( host="localhost", # 数据库主机地址 user=&q ...

  2. Eclipse Jee 2019-12 使用的一些小窍门(积累性更新)

    在安装使用 Eclipse IDE for Enterprise Java Developers  Version: 2019-12 M1 (4.14.0) 之前请确保已在系统环境变量配置好JDK1. ...

  3. mplayer 的安装步骤

        编译mplayer: make distclean ./configure --disable-png --disable-gif   //加后面的是因为编译时出错了,也可以直接  ./con ...

  4. Gre封装

    在防火墙上连  云时,可以用g0/0/0 在防火墙上不连 云时,一定不用0/0/0 !!!!!!!!! 交换机什么都不配置. FW2: interface GigabitEthernet0/0/0 u ...

  5. HashMap、Hashtable、ConcurrentHashMap、ConcurrentSkipListMap对比及java并发包(java.util.concurrent)

    一.基础普及 接口(interface) 类(class) 继承类 实现的接口 Array √ Collection √ Set √ Collection List √ Collection Map ...

  6. SpringBoot常见面试题

    什么是SpringBootSpringBoot的作用SpringBoot的优点SpringBoot的核心配置文件是什么,有何区别?SpringBoot的配置文件有几种格式,区别是什么?SpringBo ...

  7. ML modeling process

    一.数据读取Load Data 二.数据分析EDA 三.数据预处理 四.特征工程Feature engineering 五.modeling & Tuning 六.Result 七.other ...

  8. Linux把内存挂载成硬盘提高读写速度

    tmpfs是一种虚拟内存文件系统正如这个定义它最大的特点就是它的存储空间在VM里面,这里提一下VM(virtual memory),VM是由linux内核里面的vm子系统管理,现在大多数操作系统都采用 ...

  9. sql server 数据库连接方式分析、详解

    本文链接:https://blog.csdn.net/wang379275614/article/details/7859398 一.OLEDB方式连接Sql身份验证模式:Provider=" ...

  10. Java过滤器Filter的原理及配置_学习笔记

    Filter中文意思为过滤器.顾名思义,过滤器可在浏览器以及目标资源之间起到一个过滤的作用.例如:水净化器,可以看成是生活中的一个过滤器,他可以将污水中的杂质过滤,从而使进入的污水变成净水. 对于WE ...