JS的作用域和预解析

当我们使用Js 来编写一个函数的时候,总是会分不清,自己所声明的变量到底是全局变量,还是局部变量,这就牵扯到了作用域的问题。以及在函数执行的时候,函数内部的变量与全局变量及输出结果,在不同状况下的关系问题。下面就让我来举例说明一下。

作用域: 指的是代码对不同的“范围”的划分。

划分规则:

1 全局是一个作用域 这个作用域叫做全局作用域

2 只有函数,可以划分这么一个“范围”(作用域) 这样划分出来的作用域叫做私有作用域。

划分规则的应用对象: 变量

所以我们可以理解为: 作用域 划分了一个所有变量各自起作用的区域。

作用域的查找机制:

一个代码中使用到了某一个变量

首先,在这条代码当前所在的作用域中查找,如果找到了就使用 如果没有找到

向上级作用域查找,如果找到了就使用 如果没有找到

向上级作用域查找,如果找到了就使用 如果没有找到

……

重复这个过程,直到找到了,或者到了全局作用域还没有找到。此时会报一个错误 xxx is not defined

预解析:

指的是浏览器JS引擎在执行代码的过程之前,会先进行“通读”代码,在这个过程中,会将所有遇见的var定义的变量和函数声明的函数提升。

提升的位置:

如果是script标签,提升到当前script标签的最开头

如果是函数,提升到函数的函数体的最开头

作用域的特点

作用域的机制

作用域是针对变量的起作用的范围。

而变量又分为“使用变量”和“赋值变量”

使用变量

又叫做访问变量 出现在表达式中,赋值语句右侧。

访问变量规则: 当访问变量的时候,会先查看当前作用域中是否存在该变量,如果有,就使用。如果没有,就将会向上一层级作用域中寻找。依次向上,直到找到,或者到了全局作用域中还没有找到,就会报错。

赋值变量

也叫做修改变量 只出现在赋值语句左侧

赋值变量规则: 当对一个变量进行赋值的时候,会先查看当前作用域中是否存在该变量,如果有,就赋值。如果没有,就向上一层级查找。依次向上,直到找到,或者到了全局作用域中还没有找到,就会在全局作用域中悄悄的声明这个变量并赋值。

千万不要使用这个特点 切记,切忌。

// 当前是全局作用域

var num = 100; // 在全局作用域中定义的变量

// 定义一个函数

function demo() {

var num = 101; // 这是在函数作用域中定义的变量

console.log(num);

}

// 执行函数

demo(); // 101

解释: 当在函数内部访问变量num的时候,先看当前作用域中是否有num 找到了! 于是就用101 输出101

var num = 100; // 在全局作用域中定义的变量

// 定义一个函数

function demo() {

// var num; // 因为声明提升的原因 代码其实是这样子的

console.log(num);

var num = 101; // 这是在函数作用域中定义的变量 虽然定义是在这里 但是提升了

}

// 执行函数

demo(); // undefined

解释:依旧是作用域的问题,但是因为输出代码在前面,所以有些同学可能会误以为会输出100 但是不要忘记 预解析!!!

var num = 100; // 在全局作用域中定义的变量

// 定义一个函数

function demo() {

var num = 101;

}

// 执行函数

demo();

// num是多少

console.log(num); // 100

解释:作用域的问题,因为输出的代码是在全局作用域中的,所以会直接访问全局中的变量 而与函数内部的变量无关

var num = 100; // 在全局作用域中定义的变量

// 定义一个函数

function demo() {

num = 101;

}

console.log(num); // 100

// 执行函数

demo();

// num是多少

console.log(num); // 101

读代码:

1 提升

2 给全局中的num赋值为100

3 执行函数

将num赋值为101 问题的关键在于:修改的这个num到底是不是全局中的?

答案就是: 依旧是就近原则, 如果当前作用域中有声明的num变量

就修改它 如果没有向上寻找 如果找到了就修改它 如果没有找到再向上寻找

重复这个过程 直到找到或者到了全局作用域中还没有找到,就会在全局中声明这个变量并赋值

// 如果一个变量没有通过var声明 就直接赋值

num = 101; // 这种不经过声明就直接赋值而且还不会报错的特点属于JS的糟粕之一。一定不要使用。

console.log(num); // 101

console.log(num);

num = 101;

这种情况下会报错 因为num没有经过定义就被使用

疑问:

console.log(num)在使用num

难道 num = 101 不是在使用num吗?

为什么第一条console代码就会报错 而num = 101就不会报错?

因为第一个是在“访问”变量 而第二个是在“赋值”

function demo() {

num = 11;

}

demo();

console.log(num);

解读: 当demo执行的时候, num = 11 被执行 先查找num是否在当前作用域中存在,结果发现没有

没有就向上寻找,到达了全局作用域,也没有,于是就在全局作用域中,声明了该变量 所以当输出num时候,已经声明并赋值完毕

所以可以输出

当demo不执行的时候,就不会执行到这条代码 于是整个过程不会发生, num就没有被声明在全局 此时输出num时,是在访问num变量

会报错

原文地址:https://www.cnblogs.com/tongguilin/p/12229520.html

时间: 2024-08-02 04:46:40

JS的作用域和预解析的相关文章

小白学js第六天之代码规范,作用域以及预解析

目录 代码规范 命名规范 变量规范 注释规范 空格规范 换行规范 作用域 全局变量 局部变量 块级作用域 作用域链 预解析 什么是预解析 变量提升 此篇木有脑图,嘻嘻 代码规范 命名规范 变量.函数的命名必须要有意义 变量一般用名词 函数一般用动词 变量规范 操作符前后要有空格 var name = 'zs'; 注释规范 // 这里是注释 空格规范 if (true) { } for(var i = 0; i < n; i++ ) { } 换行规范 var arr = [1, 2, 3, 4];

关于作用域和预解析的不常见重要知识

作用域和预解析 在javascript中作用域是非常重要的,本文章将会说明作用域,如果有不足的地方希望大家可以评论指出来,自己一定会及时的改正错误,避免大家走入一些误区. 谈及作用域先就必须要说明预解析和词法作用域. 下面我们先说明一下: 预解析 代码在正常执行操作之前会对文档进行一次解析,这个操作就是将声明提升, 声明包括全局范围内  1.带有var的变量, 2.函数 文档预解析后会把文档中在全局函数中的内容储存起来,将全局中带有var的变量(var和变量名,注意:变量体不会随着提升,加载va

JavaScript中作用域和预解析

作用域以及预解析 在javascript中作用域是非常重要的,本文章将会说明作用域以及我们在工作,以及面试中的一些面试题,如果有不足的地方希望大家可以评论指出来,自己一定会及时的改正错误,避免大家走入一些误区. 谈及作用域先就必须要说明预解析和词法作用域. 下面我们先说明一下: 预解析 代码在正常执行操作之前会对文档进行一次解析,这个操作就是将声明提升, 声明包括全局范围内 1.带有var的变量, 2.函数 文档预解析后会把文档中在全局函数中的内容储存起来,将全局中带有var的变量(var和变量

JS作用域概念-预解析规则

// 作用域: // 域:空间.范围.区域…… // 作用:读.写 script 全局变量.全局函数 自上而下 函数 由里到外 {} 浏览器: “JS解析器” 1)“找一些东西” :var function 参数 a = ... 所有的变量,在正式运行代码之前,都提前赋了一个值:未定义 fn1 = function fn1(){ alert(2); } 所有的函数,在正式运行代码之前,都是整个函数块 JS 的预解析 遇到重名的:只留一个 变量和函数重名了,就只留下函数 2)逐行解读代码: 表达式

js全局变量与局部变量 预解析与作用域链详解

局部变量和全局变量同名时,会隐藏这个全局变量: 4.变量 关键字: 4.变量 4.1 变量的类型 JS是松散类型的语言 4.2 变量的声明 var 声明是变量的标准声明 var 声明的变量是永久性的,不能用delete运算符删除 全局对象,调用对象初始化时,JS解析器会在相应的代码段里寻找var声明的变量, 然后在全局对象,调用对象中创建相应的属性,此时它是未赋值的(undefined), 当程序执行到相应的var声明代码段时才会给相应对象的属性赋值 重复的声明:根据以上var声明作用的理解,重

JavaScript有关作用域和预解析

作用域:使用范围 全局变量:声明的变量是使用var声明的,那么这个变量就是全局变量,全局变量可以在页面的任何位置使用 除了函数以外,其他的任何位置定义的变量都是全局变量 局部变量:在函数内部定义的变量,是局部变量,外面不能使用 全局变量,如果页面不关闭,那么就不会释放,就会占空间,消耗内存 全局作用域:全局变量的使用范围 局部作用域:局部变量的使用范围 块级作用域:一对大括号就可以看成是一块,在这块区域中定义的变量,只能在这个区域中使用,但是在js中在这个块级作用域中定义的变量,外面也能使用;

作用域和预解析

// 作用域: // 域:空间.范围.区域…… // 作用:读.写 script 全局变量.全局函数 自上而下 函数 由里到外 {} 浏览器: “JS解析器” 1)“找一些东西” :var function 参数 a = ... 所有的变量,在正式运行代码之前,都提前赋了一个值:未定义 fn1 = function fn1(){ alert(2); } 所有的函数,在正式运行代码之前,都是整个函数块 JS 的预解析 遇到重名的:只留一个 变量和函数重名了,就只留下函数 2)逐行解读代码: 表达式

作用域,预解析,对象,内置方法 Math Date Array

作用域 一段程序代码中所用到的名字并不总是有效可用的,而限定这个名字(变量)的可用性的代码范围,就是这个名字的作用域,作用域提高了逻辑程序的局部性,增强了可靠性,减少了名字冲突: JavaScript作用域(es6)之前:全局作用域,局部作用域 全局作用域:整个script标签或者是一个单独的JS文件 局部作用域(函数作用域):在函数内部就是作用域: 变量作用域 全局变量:在全局作用域下声明的变量:如果在函数内部没有声明(var)直接赋值的变量也是全局变量 num = 2; 局部变量:在函数内部

javascript里面的闭包,作用域,预解析

函数的作用域 1.全局变量=公用卫生间 2.局部变量=次卧卫生间      局部变量 全局无法使用      局部声明变量不加var的话就变成全局变量(不推荐使用) 3.闭包=次卧的可以用自己的卫生间,也可以用公用卫生间: 预解析 1.先把变量声明 全部提前,赋值不动 2.函数也有预解析,直接提前   3.预解析 不会脱离函数作用域,也不会冲出script标签 最多提到自己标签的顶部 代码执行顺序 见一个srcipt解析执行一个,执行完了 在执行下一个 案例1:      alert(a);