day8JS-作用域

1. 变量的作用域(变量+函数)

        作用域变量的可作用范围变量只有在自己的作用域下才会生效。

        函数会产生作用域,在函数内定义的变量只能在函数内使用

2. 作用域分类

        局部作用域函数内定义的变量和形参的作用域就是局部作用域;这样的变量称之为局部变量

        全局作用域: 在函数外面定义的变量的作用域是全局作用域;这样的变量称之为全局变量

        块级作用域(es6新增)在代码块中定义的变量的作用域是块级作用域;这样的变量称之为块级变量ES6才支持,必须使用es6的声明方式。

局部变量 只能在定义变量函数内使用全局变量任意地方都可以使用

注意:函数内的形参也是局部变量,作用域范围就是所在函数。

了解:函数内不使用关键字 var 声明的变量,因为会被当做全局变量,但不建议这么做,在严格模式下,不使用关键字 var 就声明变量,会报错!

3. 哪些关键字声明会产生作用域?

3.1 es5的关键字

var
function

3.2 es6的关键字

let
const
class

4. 作用域的案例

1. a、b 都是在全局下定义的,所以他们的作用域就是全局,n是在fn中定义的,它的作用域就是fn函数中。

var a=3;
var b=6;
function fn(){var n=3;console.log(n)
};
console.log(a,b);//3 6

2. 在全局下定义的变量,在哪都可以访问到,在私有作用域中定义的变量,在外面是访问不到的。

var a=3;function fn(){var b=6;console.log(a); //3
}fn();
console.log(b);//报错

3. 作用:隔离变量,不同作用域下同名变量不会有冲突。

var a = 10,b = 20;
function fn(x) {//x = 10var a = 100,c = 300;console.log('fn()', a, b, c, x)//"fn()" 100 20 300 10function bar(x) {//x = 100  200var a = 1000,d = 400console.log('bar()', a, b, c, d, x)//"bar()" 1000 20 300 400 100//"bar()" 1000 20 300 400 200}bar(100)bar(200)
}
fn(10)

全局变量和私有变量

全局变量(VO):在全局作用域中定义的变量就是全局变量。

私有变量(AO):在私有作用域中定义的变量就是私有变量。例如函数体内声明的形参和在函数私有作用域中定义的变量

5. 浏览器底层运行机制

1. ECStack(Execution context Stack)执行环境栈(栈内存,从内存中分配出来的一块内存)。

2. EC(Execution Context)执行上下文(在编程语言中,代码执行,为了区分全局作用域和函数执行所处不同的作用域,目的是为了区分每个词法作用域下代码的独立性)EC 就是代码执行所处的范围。

  • EC(g)全局执行上下文。
  • EC(function)函数执行的上下文。

3. VO 和AO:在每一个执行上下文中,代码执行的时候,都会存贮一些变量:

  • 全局上下文中的变量存储在VO
  • 私有上下文中的变量存储在AO

4. GO:浏览器把一些内置的属性和方法放到了GO中,并且在全局执行上下文(EC(g))中创建了一个window变量对象,并且让其指向GO

代码案例的执行流程:

6. 作用域链

6.1 什么是作用域链

  • 函数会限制变量的作用域范围,而函数内是可以再嵌套函数的,函数的层层嵌套,就形成了一个作用域链
  • 作用域链描述的是程序在执行过程当中寻找变量的过程。

6.2 作用域链寻找变量的过程

当函数内使用某个变量的时候,会按照如下过程找到该变量:

  • 先从自身所在作用域去查找,如果没有再从上级作用域当中去查找,直到找到全局作用域当中。
  • 如果其中有找到,就不会再往上查找,直接使用
  • 如果都没有找到,那么就会报引用错误提示变量没有定义

6.3 注意

一个变量的作用域只与函数声明的位置有关与函数调用的位置无关

function fn(){// 自己私有作用域没有这个变量,向上级进行查找,上级window 也没有,就报错console.log(n);//报错
}
fn();

只有赋值,没有声明关键字的案例: 

function fn(){n=3; // 自己私有作用域中没有,向上级进行查找,上级作用域也没有,就相当于给window.n=3;
}
fn();
console.log(n);

 

function fn(){n=3; // 自己私有作用域中没有,向上级进行查找,上级作用域中有,就是上级作用域的n的值重新改了3
}
var n=2;
fn();
console.log(n);

function fn(){console.log(n);// 2
}
var n=2;
fn();
console.log(n);

7. 变量提升

7.1 什么是变量提升?

        当浏览器开辟出供js执行的栈内存之后,代码并不是立即自上而下执行,而是需要先做一些事情:把当前作用域中带var 和function 的关键字进行提前的声明和定义,这叫做变量提升机制es5的关键字才有变量提示,es6的关键字没有有变量提示。

7.2 var 和 function 在变量提升阶段区别

  • var 在变量提升阶段是只声明,未定义(不赋值),赋值留在原地
  • function 在此阶段是声明和定义(赋值)都完成(声明+赋值)

注意特殊情况!!!

        1.var 如果遇到 if,不论判断条件是否成立都会不影响变量提升

        2.function如果遇到 if,第一步先声明提前不赋值,第二步再看 if 判断是否成立成立进入到if 中,以要变量提升的函数为界,分为上级作用域私有作用域(块级作用域第三步进入if(上级作用域)立刻重新变量提升声明+赋值,然后其它代码自上而下的执行;进入到私有块级作用域立刻重新变量提升声明+赋值,然后其它代码自上而下的执行。

        3.function如果遇到 if,判断条件不成立,直接进行变量提升只声明,不赋值

       

        4.【f =  function(){}】的函数自执行函数没有变量提升如果自执行函数有中有像function 函数名(){}这样的函数还是要声明提前+赋值。

        5.像【声明关键字 f  =  function(){}这样使用表达式定义的函数function只对等号左边做变量提升

        

        6.return 下面的代码进行变量提升return 后面的代码不进行变量提升。

       

        7.如果变量名字重复var不会进行重复声明,但是会重新赋值,在变量提升阶段,看到第一行var num ,会声明一个变量num,此时看到第二行还有一个就不用再声明了。function的在变量提升阶段是声明和定义一起完成的,如果遇到重复声明定义的,会进行重新赋值

7.3 var 变量提升原理

7.3.1 var 变量提升后的代码执行流程

var变量提升,声明提前,赋值还在原来的位置。

 7.3.2 var 变量提升案例

案例1:

<body><script>console.log(a); var a = 10;console.log(a);</script>
</body>--------------------
变量提升
<body><script>var a;console.log(a); //undefineda = 10;console.log(a);//10</script>
</body>

案例2:

<body><script>console.log(a);if (1 == "2") {var a = 12;}console.log(a);</script>
</body>-----------------
变量提升
<body><script>var a;console.log(a);//undefined// if判断不成立,无法进入if (1 == "2") {a = 12;}console.log(a);//undefined</script>
</body>

案例3:

<body><script>console.log(a);if (a in window) {var a = 100;}console.log(a);</script>
</body>---------------------
变量提升
<body><script>var a;console.log(a);//undefined// if判断成立,进入执行if中的代码if (a in window) {a = 100;}console.log(a);//100</script>
</body>

 7.4 function 变量提升原理

7.4.1 function 变量提升后的代码执行流程

function变量提升,声明和赋值都提前。

 7.4.2 function 变量提升案例 

1. function 普通的变量提升

案例:

<body><script>let a;function fn() {a = 100;}fn();console.log(a);//100</script>
</body>

2. 遇到if不成立的情况,function只声明不赋值。

案例1:

<body><script>//遇到if不成立的情况,function只声明不赋值console.log(fn);//undefinedif (1 == "2") {function fn() { }} console.log(fn);//undefined</script>
</body>-----------------------------
变量提升后
1.遇到if先提前声明。 
function fn;
console.log(fn);2.if不成立,if中的语句不执行。
if (1 == "2") {function fn() { }
} 
3.最后只声明了函数没有赋值,所以是undefined
console.log(fn);

案例2:

<body><script>//遇到if不成立的情况,function只声明// 1.先声明提前console.log(fn);//undefinedif (1 == "2") {console.log(fn);function fn() { }console.log(fn);}console.log(fn);//undefined</script>
</body>----------------------
变量提升后
1.遇到if先提前声明。 
function fn;
console.log(fn);//undefined2.if不成立,if中的语句不执行。
if (1 == "2") {console.log(fn);function fn() { }console.log(fn);}3.最后只声明了函数没有赋值,所以是undefined
console.log(fn);

3. 遇到 if 成立的情况,先声明提前,赋值还在原来位置,后面是重新function声明+赋值。

案例1:

<body><script>//遇到if成立的情况,function声明+赋值// 1.先声明提前console.log(fn);//undefinedif (1 == "1") {console.log(fn);//函数体ƒ fn() { }function fn() { }console.log(fn);//函数体ƒ fn() { }}console.log(fn);//函数体ƒ fn() { }</script>
</body>

分析:

4. 【f =  function(){}】的函数自执行函数没有变量提升如果自执行函数有中有像function 函数名(){}这样的函数还是要声明提前+赋值。

f=function(){return true;
};
g=function(){return false;
};
~function(){if(g()&&[]==![]){f=function(){return false;};function g(){return true;}}
}();
console.log(f());//报错
console.log(g());-------------------------
变量提升
f=function(){return true;
};g=function(){return false;
};~function(){if(g()&&[]==![]){function g(){return true;}f=function(){return false;};}
}();
console.log(f());//报错
console.log(g());

5. 有声明关键字 f  =  function(){}function只对等号左边的做变量提升。

案例1:

console.log(fn);//undefined
console.log(fn(1,2));//报错
var fn=function (n,m){return n+m;}
console.log(fn(3,4));----------------------------
变量提升
var fn;
console.log(fn);//已声明,没有赋值undefinedconsole.log(fn(1,2))//undefined(1,2)报错fn = function (n,m){return n+m;}
console.log(fn(3,4))

案例2:

sum();//2
fn();//报错
var fn=function(){console.log(1);
};function sum(){console.log(2);
}fn();
sum();---------------------------
变量提升
var fn;
function sum(){console.log(2);
}sum();//2
fn();//报错信息:fn is not a function 现在的fn是普通变量不是函数fn = function(){console.log(1);
};fn();
sum();

案例3:

console.log(obj.f1);//报错TypeError: Cannot read properties of undefined (reading 'f1')
var obj={f1:function(){console.log(1)}---------------------------
变量提升
var obj;console.log(obj.f1);//只声明了变量名,还没有创建出对象,现在是无法访问对象属性的obj={f1:function(){console.log(1)}
}

5. return 下面的代码进行变量提升,return 后面的代码不进行变量提升。

案例1:

function fn(){console.log(a);return function f1(){}var a=3;
}
fn();---------------------------
变量提升
var a;
function fn(){console.log(a);//undefinedreturn function f1(){}a=3;
}fn();

 案例2:

function fn(){console.log(f2);return function f1(){}function f2(){console.log("f2")}
}
fn();------------------
变量提升
function fn() {function f2() {//声明并赋值console.log("f2")}console.log(f2);//函数体/*ƒ f2() {console.log("f2")}*/return function f1() {}}fn();

7.5 综合练习

<body><script>//遇到if成立的情况,function声明+赋值// 第一轮:先声明提前var a = 0;// if成立,以函数为界限,分为上级作用域和块级私有域if (true) {a = 1;function a() { }a = 21;console.log(a);//21}console.log(a);//1</script>
</body>分析:
第一轮:变量提升
var  a;
a = 0;
if成立,以函数为界限,分为上级作用域和块级私有域第二轮:变量提升
声明函数function a
var a 与 function a()重名,所以变量a变成了函数a。
进入if立刻重新变量提升声明函数+赋值
函数a = 1;
--------------------以函数为界限---------------------
第二轮:变量提升
函数a = 21;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/409558.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot的酒店管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot框架技术 工具&#xff1a;IDEA/Eclipse、Navicat、Maven 系统展示 首页 用户注册界面…

rabbitMQ安装与简单demo

安装 mac安装有了brew很方便&#xff0c;windows的可参考 win10 安装rabbitMQ详细步骤 brew install rabbitmq启动 brew services start rabbitmq关闭 brew services stop rabbitmq出了问题之后可以重启一下 brew services restart rabbitmqsome issue 某些库下载超时 比…

学习笔记七:基于Jenkins+k8s+Git+DockerHub等技术链构建企业级DevOps容器云平台

基于Jenkinsk8sGitDockerHub等技术链构建企业级DevOps容器云平台 安装Jenkins在kubernetes中部署jenkins创建名称空间创建pv,上传pv.yaml创建pvc创建一个sa账号通过deployment部署jenkins更新资源清单文件把jenkins前端加上service&#xff0c;提供外部网络访问 配置Jenkins获取…

PeriodWave: Multi-Period Flow Matching for High-Fidelity Waveform Generation

preprintKorea Seoul, Korea 文章目录 abstractmethodFlow Matching for Waveform GenerationHigh-frequency Information Modeling for Flow Matching demo page&#xff0c; PeriodWave 三者最好&#xff0c;而且能把原声中的噪声去掉&#xff0c;GAN一类声码器做不到的。 Pe…

Unity编辑器扩展之Project视图扩展

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity编辑器扩展之Project视图扩展 TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取&#xff01…

一家物流装备企业终止,业绩下滑严重,恐不符合创业板新上市标准

鸿安机械终止的原因如下&#xff1a;首先&#xff0c;报告期内鸿安机械的营业收入和净利润出现下滑趋势&#xff0c;公司最近一年净利润恐不达标&#xff0c;或许不能满足创业板更新的第一套上市标准&#xff1b;其次&#xff0c;鸿安机械经营业绩对比同行业可比公司&#xff0…

智能优化特征选择|基于鹦鹉优化(2024年新出优化算法)的特征选择(分类器选用的是KNN)研究Matlab程序 【优化算法可以替换成其他优化方法】

智能优化特征选择|基于鹦鹉优化&#xff08;2024年新出优化算法&#xff09;的特征选择&#xff08;分类器选用的是KNN&#xff09;研究Matlab程序 【优化算法可以替换成其他优化方法】 文章目录 一、PO基本原理PO基本原理基本流程示例应用 二、实验结果三、核心代码四、代码获…

gitlab使用教程

一、定义 pycharm 克隆代码pycharm 克隆分支type 提交指令使用可视化界面SourceTreepycharm中git 基本使用获取和拉取的区别&#xff0c;update project 区别sourceTree 回退版本sourceTree 回滚代码 二、实现 教程&#xff1a; https://liaoxuefeng.com/books/git/gui/inde…

在DDD中应用模式

深层模型和柔性设计并非唾手可得。要想取得进展&#xff0c;必须学习大量领域知识并进行充分的讨论&#xff0c;还需要经历大量的尝试和失败。但有时我们也能从中获得一些优势。一位经验丰富的开发人员在研究领域问题时&#xff0c;如果发现了他所熟悉的某种职责或某个关系网&a…

Nosql数据库redis集群配置详解

一、Redis的安装 环境介绍&#xff1a; 一主双从&#xff1a;10&#xff08;redis-node1&#xff09;主&#xff0c;20&#xff08;redis-node2&#xff09; 30&#xff08;redis-node3&#xff09;从——使用的是红帽9.1系统 源码安装redis [rootredis-node1 ~]# tar zxf red…

前端常见问题

一、<!DOCTYPE html>作用 <!DOCTYPE>是html文档的第一行&#xff0c;用于声明文档的类型&#xff0c;它会告诉浏览器要用哪一种HTML规范来渲染文档&#xff0c;确保正确渲染页面。 二、src与 href 的区别 &#xff08;一&#xff09;、请求资源类型的不同 在请…

女明星玩乙游,为何会推动国乙玩家“世纪大和解”?

“震惊&#xff01;叠姐和光姐竟然世纪大和解了。” 这件在国乙圈匪夷所思、想都不敢想的事&#xff0c;竟然在一位女明星的推动下发生了&#xff0c;也因此诞生了国乙圈的“8.22事件”。 事情的起因是女艺人乃万在社交平台上发布了乙游相关言论&#xff0c;引起了乙游玩家不…

Spring--三级缓存机制

一、什么是三级缓存 就是在Bean生成流程中保存Bean对象三种形态的三个Map集合&#xff0c;如下&#xff1a; // 一级缓存Map 存放完整的Bean&#xff08;流程跑完的&#xff09; private final Map<String, Object> singletonObjects new ConcurrentHashMap(256);// 二…

USB3.2 摘录(九)

系列文章目录 USB3.2 摘录&#xff08;一&#xff09; USB3.2 摘录&#xff08;二&#xff09; USB3.2 摘录&#xff08;三&#xff09; USB3.2 摘录&#xff08;四&#xff09; USB3.2 摘录&#xff08;五&#xff09; USB3.2 摘录&#xff08;六&#xff09; USB3.2 摘录&…

页面设计任务 商品详情页(带评论区)

目录 效果图&#xff1a; 任务描述 源码&#xff1a; 详细讲解&#xff1a; 1.产品信息部分 2.用户评论区域 效果图&#xff1a; 任务描述 页面结构: 页面应包括一个标题部分、一个产品展示区和一个客户评价区。使用图片展示产品&#xff0c;并添加描述。客户评价区展示一…

IP代理池学习记录

免责声明 本文仅供学习和研究目的使用。所提供的信息和技术仅限于合规和合法的使用场景。请读者在应用相关技术时遵守法律法规&#xff0c;尊重他人的数据隐私和网站使用条款。本文作者对因使用本文信息而产生的任何法律责任或损失不承担责任。 1、初识IP代理池 概述&#xff…

如何使用ssm实现基于SSM的社区物业管理系统的设计与实现+vue

TOC ssm223基于SSM的社区物业管理系统的设计与实现vue 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利化&…

Redis—缓存机制

Redis 缓存机制 1. 缓存三兄弟1.1 缓存击穿1.2 缓存穿透1.3 缓存雪崩 2. 布隆过滤器3. 缓存和数据库数据一致性3.1 缓存更新策略3.2 缓存不一致处理 4. 热点 key4.1 热点 key 处理4.2 热点 key 重建 5. 缓存预热 Redis&#xff0c;一个轻量级的开源内存数据结构存储系统&#x…

Redis计数器:数字的秘密

文章目录 Redis计数器incr 指令用户计数统计用户统计信息查询缓存一致性 小结 技术派项目源码地址 : Gitee :技术派 - https://gitee.com/itwanger/paicodingGithub :技术派 - https://github.com/itwanger/paicoding 用户的相关统计信息 文章数&#xff0c;文章总阅读数&am…

go设计模式——单例模式

概念 单例是一种创建型设计模式&#xff0c;它确保一个类在整个程序运行期间只有一个实例&#xff0c;并提供一个全局访问点来使用该实例。虽然单例模式在某些情况下非常有用&#xff0c;例如管理全局配置、日志记录或资源共享&#xff0c;但它也带来了与全局变量相似的问题。…