一、作用域

1、什么是作用域(Scope)

通常来说,一段程序代码中所用到的名字不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

JS作用域:就是代码名字(变量)作用的范围

作用域的目的:是为了提高程序的可靠性,更重要的是减少命名冲突

2、JS的作用域的分类(ES6之前)

JS作用域可以分为两大类:全局作用域 、局部作用域(函数作用域)

(一)全局作用域:

  直接编写在 script 标签之中的JS代码,都是全局作用域;

  或者是一个单独的 JS 文件中的。

  全局作用域在页面打开时创建,页面关闭时销毁;

  在全局作用域中有一个全局对象 window(代表的是一个浏览器的窗口,由浏览器创建),可以直接使用。

在全局作用域中,

  • 所有创建的变量都会作为 window 对象的属性保存。

  • 所有创建的函数都会作为 window 对象的方法保存。

(二)局部作用域(函数作用域):

  在函数内部就是局部作用域,这个代码的名字只在函数的内部起作用

  调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁;

  每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的。

实例分析:

在这个例子里面 un函数里面的 局部作用域中 有一个 num 变量,script 标签的全局作用域中也有一个 num变量。

(一个在全局作用域下,另一个在局部作用域下,虽然两个变量的变量名相冲突,但是并没有影响。)

所以,在不同的作用域下,变量名相同也不受影响,这样就很有效的减少了命名冲突。

<script>
var num = 10;
function nu(){
var num = 20;
console.log(num);
}
nu();
console.log(num);
</script>

JS现阶段(ES6之前)没有块级作用域,被块级作用域就是用大括号({})包含的就是块级作用域。

二、变量的作用域

在JavaScript中,根据作用域的不同,变量可以分为两种:全局变量局部变量

(一)全局变量

  1、在全局作用域下声明的变量叫做 全局变量(在函数外部定义的变量)

  2、全局变量在全局(代码的任何位置)下都可以使用;全局作用域中无法访问到局部作用域中的变量。

  3、全局变量第一种创建方式:在全局作用域下 var声明的变量是全局变量

  4、全局变量第二种创建方式:如果在函数内部,没有使用 var关键字声明直接赋值的变量也属于 全局变量。(不建议使用)

(变量 num 直接写在 script标签下,所以 num是全局变量。)

<script>
var num = 10;
function nu(){
console.log(num);
}
nu();
console.log(num);
</script>

 (二)局部变量:

  1、在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)

  2、局部变量只能在函数内部使用,在局部作用域中可以访问到全局变量。

  3、在函数内部 var 声明的变量就是局部变量

  4、函数的形参实际上就是局部变量

<script>
function nu(){
var num1 = 10;
num2 = 20;
console.log(num1);
}
nu();
console.log(num2);
</script>

(三)全局变量和局部变量的区别:

全局变量:在任何一个地方都可以使用,全局变量只有在浏览器关闭的时候才会销毁,比较占用内存资源

局部变量:只能在函数内部使用,当其所在代码块被执行时,会被初始化;当代码块执行完毕就会销毁,因此更节省节约内存空间;

三、变量的声明提前和函数的声明提前

(一) 变量的声明提前

使用 var 关键字声明的变量,会在所有的代码执行之前被声明。(但是不会赋值)

全局变量即使是写在最下面,也相当于在所有代码之前的最上面声明的变量。

  等价于 

(在这个例子中最终结果返回的是 undefined,这是因为 变量a 就相当于在所有代码最上面被声明,但下面才被赋值,所以结果是 undefined未定义)

如果声明变量的时候不使用 var 关键字,那么变量就不会被声明提前。

 

(如果不写 var 关键字,变量声明就无法提前,所以在 console.log前面就找不到 变量,所以返回结果报错)

(二) 函数的声明提前

使用函数声明形式创建的函数 :function 函数名() {};

它会在所有代码执行之前就被创建。所以可以在函数声明之前被调用

等价于

使用函数表达式创建的函数:var 变量名 = function(){};

不会被声明提前,所以不能再声明前调用。

四、作用域链

只要是代码,就有一个作用域,写在函数内部的就叫做局部作用域;

如果函数中还有函数,那么在这个作用域中又可以诞生一个作用域;

当在函数作用域中操作一个变量的时候,会先在自身作用域中查找,如果有就直接使用,如果没有就向上级作用域中寻找。如果全局作用域中也没有,那么就报错。

根据内部函数可以访问可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称为函数作用域链

作用域链:内部函数访问外部函数的变量,采取的是链式查找的方法来决定取那个结构,这种结构称之为作用域链

作用域链的原则:就近原则

(作用域链采用链式查找的方式,一层一层向上查找,先查找外面的嵌套的函数是否有所需内容,找到就输出相应的结果,如果没有再向上查找。就近原则

实例一:


下面代码最终输出的结果是多少?

 思路分析:

按照链式查找先到上一级查找,输出内容在2级链,向上到 1级链去查找,如果 1级链也没有就继续向上查找。如果都找不到就会返回 undefined(未定义)。

因为1级链中有 unm 值,所以输出num结果就是 123。

实例二:


下面代码最终输出的结果?

注意:在更长的结构中画图分析太过于麻烦,可以从输出目标console.log(); 位置向外层的结构看,寻找最近的变量。

var a = 1;
function fn1(){
var a=2;
var b='22';
fn2();
function fn2(){
var a =3;
fn3();
function fn3(){
var a=4;
console.log('a= ' + a); //求 a的值
console.log('b= ' + b); //求 b的值
}
}
}
fn1();

最终结果是:

JS 全局作用域和局部作用域的更多相关文章

  1. JavaScript基础&实战(4)js中的对象、函数、全局作用域和局部作用域

    文章目录 1.对象的简介 2.对象的基本操作 2.1 代码 2.2 测试结果 3.属性和属性值 3.1 代码 3.2 测试结果 4.对象的方法 4.1 代码 4.2 测试结果 5.对象字面量 5.1 ...

  2. 【Laravel】为Eloquent 模型设置全局作用域和局部作用域进行查询

    全局作用域 所谓「全局作用域」,指的是预置过滤器在注册该「全局作用域」的模型类的所有查询中生效,不需要指定任何额外条件. 以 User 模型类为例,我们在系统中可能只想针对已经验证过邮箱的用户进行操作 ...

  3. eval全局作用域和局部作用域的坑!

    1.eval 是个函数,他可以被赋值给变量,例如   var evalg = eval;  evalg("alert(1)"); 2.eval被赋值时,也会把当前eval所处的变量 ...

  4. vue.js全局组件和局部组件区别

    在id=‘#app’,加入<pl>标签,但也访问不了局部chil组件: 在id=‘#div0’,加入<as>标签,但能访问到全局组件

  5. js 函数 作用域 全局作用域 局部作用域 闭包

    一个变量没有声明但调用 直接报错,声明没有赋值会显示未定义. 作用域 作用域(scope):一条数据可以在哪个范围中使用. 通常来说,一段程序代码中所用到的数据并不总是有效/可用的,而限定这个数据的可 ...

  6. js全局作用域

    全局作用域 不在任何函数内定义的变量就具有全局作用域.实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性: var course = 'L ...

  7. [ python ] 全局和局部作用域变量的引用

    全局与局部变量的引用 (a)locals(b)globals 这里还需要在补充2个关键字一起比较学习,关键字:(c)nonlocal(d)global locals 和 globals locals: ...

  8. javascript - 全局与局部作用域

    // 全局作用域 var globalNumber = 1; // 挂载在window上的变量或函数 -> 全局作用域 function InternalScope() { // 局部作用域 / ...

  9. 关于js中变量声明和作用域的理解

    1. var是声明一个变量:虽然声明了这个变量,但在存入值之前,它的初始值是 undefined:2.全局变量:拥有全局作用域,在js代码中的任何地方都是有定义的:3.局部变量:在函数内声明的变量只在 ...

随机推荐

  1. Mongo分片+副本集集群搭建

    一. 概念简单描述 1. MongoDB分片集群包含组件: mongos,configserver,shardding分片 2. Mongos:路由服务是Sharded cluster的访问入口,本身 ...

  2. # IDEA相关知识

    目录 IDEA相关知识 安装目录下: 配置目录下: 工程目录下: 名词解释 IDEA相关知识 安装目录下: bin:启动文件,配置信息,IDEA的一些属性信息 jre64:IDEA自带的运行环境 li ...

  3. 用纯 CSS 创作一个在容器中反弹的小球

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/jKVbyE 可交互视频教 ...

  4. 比特(bit)和字节(Byte)

    比特(bit)和字节(Byte) 基础的内容就不说了,这里是一个小的学习笔记 比特和字节的写法差异与应用场景 标准的写法中,正如标题中写的那样,是通过大小写来区分比特和字节的:比特的b应该是小写,而字 ...

  5. qt webengineview 加载本地资源方式

    一.如果把资源添加到本地资源qrc库里了,请使用 ui->preview->setUrl(QUrl("qrc:/HelloWorld2.html")): 二.如果没有现 ...

  6. 这十个MySQL经典错误

    今天就给大家列举 MySQL 数据库中,最经典的十大错误案例,并附有处理问题的解决思路和方法,希望能给刚入行,或数据库爱好者一些帮助,今后再遇到任何报错,我们都可以很淡定地去处理.学习任何一门技术的同 ...

  7. 关于redis的几件小事(七)redis缓存雪崩与穿透

    1.缓存雪崩 (1)什么是缓存雪崩 缓存雪崩指的是在同一时刻,缓存大量失效,导致大量的请求直接到了数据库,数据库压力剧增,引起系统崩溃.可能出现的情况有: ①大量的key设置了相同的过期时间,导致在缓 ...

  8. python调用接口的方式

    python中调用API的几种方式: - urllib2 - httplib2 - pycurl - requests urllib2 import urllib2, urllib github_ur ...

  9. 94. Binary Tree Inorder Traversal (Java)

    Given a binary tree, return the inorder traversal of its nodes' values. Example: Input: [1,null,2,3] ...

  10. Systemctl和service、chkconfig命令的关系

      systemctl命令:是一个systemd工具,主要负责控制systemd系统和服务管理器. service命令:可以启动.停止.重新启动和关闭系统服务,还可以显示所有系统服务的当前状态. ch ...