day8JS-作用域

news2024/11/17 7:51:43

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 = 10
    var a = 100,
        c = 300;
    console.log('fn()', a, b, c, x)//"fn()" 100 20 300 10
    function bar(x) {//x = 100  200
        var a = 1000,
            d = 400
        console.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); //undefined
        a = 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);//undefined
        if (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);//undefined
        if (1 == "2") {
            console.log(fn);
            function fn() { }
            console.log(fn);
        }
        console.log(fn);//undefined
    </script>
</body>

----------------------
变量提升后
1.遇到if先提前声明。 
function fn;
console.log(fn);//undefined

2.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);//undefined
        if (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);//已声明,没有赋值undefined

console.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);//undefined

   return 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.coloradmin.cn/o/2076095.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Hot100】LeetCode—207. 课程表

目录 1- 思路有向图记录入度数组出度列表 2- 实现⭐207. 课程表——题解思路 3- ACM 实现 题目连接&#xff1a;207. 课程表 1- 思路 有向图记录入度数组出度列表 根据输入① 构造遍历构造入度数组② 构造出度列表根据入度数组为 0 的数 加入到 队列中&#xff0c;进行处理 2…

在线拼图用什么软件?5款顶级照片拼接工具

照片拼接在一起用什么软件&#xff1f;当你想全景展现山西应县木塔的震撼之美时&#xff0c;5款精选照片拼接软件能帮你解锁全新视角。 这座千年古塔&#xff0c;巍峨耸立&#xff0c;细节之处尽显匠心独运。而通过拼接技术&#xff0c;每一块木构的精致、每一层塔檐的飞翘都能…

OpenBayes 教程上新 | 青岛小哥焦恩俊版二郎神来袭,MuseV + MuseTalk 分分钟实现高质量数字人制作!

使用传统的数字人训练方案生成一个高质量的数字人&#xff0c;常常需要大量的时间和算力资源&#xff0c;同时对训练素材的要求也较高&#xff0c;如果想要达到良好的唇形一致效果&#xff0c;通常需要数小时乃至更久。 MuseV 和 MuseTalk 的出现为数字人领域带来了新的突破&a…

【Canvas与桌面】十字网格黑灰背景(1920x1080)

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>十字网格黑灰背景(1920x1080)</title><style type"te…

iphone被锁定怎么解锁?iPhone密码锁解锁办法分享

在忙碌的生活中&#xff0c;有时我们可能会遇到一些“小插曲”&#xff0c;比如苹果手机被锁定&#xff0c;iPhone被锁定是一个常见的问题&#xff0c;可能是由于忘记密码、多次输入错误密码或设备被远程锁定等原因造成的。 本文将介绍解锁被锁定的iPhone的方法以及注意事项&a…

【网络安全】IDOR之请求包分析

未经许可,不得转载。 文章目录 正文正文 某在线游戏平台,在开始测试时,我访问了 /profile 页面(个人资料页面),然后查看 Burp 历史记录,想查看有多少隐藏的请求。 可以看到一个HTTP 的 OPTIONS 方法的请求包: 从图中看到,该请求包含两个参数:player_id_or_name(用…

OpenHarmony源码解析之电话子系统——通话流程

一、简介 OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;电话子系统为 OS 提供了基础的无线通信能力。 支持 TD-LTE/FDD-LTE/TD-SCDMA/WCDMA/EVDO/CDMA1X/GSM 等网络制式的通信模块&#xff0c;能够提供高速的无线数据传输、互联网接入等业务&#xf…

c++栈和队列(stack和queue)

前言 栈和队列是两个极其相似的数据结构&#xff0c;栈具有先进后出的特性&#xff0c;队列具有先进先出的特性。今天我们就来简单的介绍一下栈和队列这两数据结构&#xff0c;其中队列我们介绍普通队列、双端队列&#xff08;了解&#xff09;和优先级队列&#xff08;其实这…

C++从入门到起飞之——vector模拟实现 全方位剖析!

​ &#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1、vector的成员变量 2、迭代器 3、size与capacity 4、[]运算符重载 5、reserve 6、push_bac…

LSTM结合时序异常检测直接写!小论文闭着眼睛发!

还在愁小论文&#xff1f;不如考虑考虑这个方向&#xff1a;LSTM时间序列异常检测。 这是个比较活跃且热门的研究方向&#xff0c;因为LSTM具有非常优秀的时序数据深度处理能力&#xff0c;能够灵活适应不同复杂度的数据&#xff0c;给我们提供高精度的预测结果&#xff0c;在…

时间继电器和定时器

一、概述 1.时间继电器是可以在设定的定时周期内或周期后闭合或断开触点的元器件。 2.时间继电器上可设定的定时周期数量有限&#xff0c;多为一个或两个。定时时长从0.02s至300h(根据产品型号范围不同)。 3.定时器可以理解为一台钟表&#xff0c;它在某个时间点上闭合(断开…

PostgreSQL如何设置主键自增(序列、SERIAL)

文章目录 PostgreSQL如何设置主键自增背景什么是序列Postgresql的自增机制基本使用使用SERIAL或BIGSERIAL数据类型手动创建序列和设置默认值实战demo&#xff1a;PostgreSQL 手动序列管理设置序列的当前值 工作常用总结创建表时候自定义序列&#xff1a;id SERIAL PRIMARY KEY …

调用具体接口的所有实现类

Java获取接口的所有实现类方法-CSDN博客https://blog.csdn.net/feeltouch/article/details/135399078

最实用接地气的 .NET 微服务框架

目录 前言 项目介绍 快速入门 1、服务注册 2、启动UI 3、服务发现与调用 4、启动服务网关 项目地址 最后 前言 微服务架构已经成为搭建高效、可扩展系统的关键技术之一&#xff0c;然而&#xff0c;现有许多微服务框架往往过于复杂&#xff0c;使得我们普通开发者难以…

基于生成对抗模型GAN蒸馏的方法FAKD及其在EdgesSRGAN中的应用

文章目录 FAKD系列论文paper1: FAKD&#xff1a;用于高效图像超分辨率的特征亲和知识蒸馏&#xff08;2020&#xff09;ABSTRACT1. INTRODUCTION2. PROPOSED METHOD2.1. Feature Affinity-based Distillation (FAKD) 2.2. Overall Loss Function3. EXPERIMENTAL RESULTS3.1. Ex…

TypeSript9 命名空间namesapce

我们在工作中无法避免全局变量造成的污染&#xff0c;TypeScript提供了namespace 避免这个问题出现 内部模块&#xff0c;主要用于组织代码&#xff0c;避免命名冲突。命名空间内的类默认私有通过 export 暴露通过 namespace 关键字定义 TypeScript与ECMAScript 2015一样&…

React学习day02-React事件绑定、组件、useState、React组件样式处理方式

3、React事件绑定&#xff08;以点击事件为例&#xff09; &#xff08;1&#xff09;语法&#xff08;整体遵循驼峰命名法&#xff09;&#xff1a;on事件名称{事件处理程序} 比如&#xff1a;点击事件onClick&#xff08;类似于vue中的click&#xff09; &#xff08;2&…

成为Python高手,我能给出的最好建议

今天笔者将向大家分享5个良好的Python编程习惯&#xff0c;大牛认证&#xff0c;通过不断实践&#xff0c;助你写出更Pythonic的代码&#xff0c;让你向Python大师之路更进一步。 今天笔者将向大家分享5个良好的Python编程习惯&#xff0c;大牛认证&#xff0c;通过不断实践&a…

Java面试题精选:消息队列(二)

一、Kafka的特性 1.消息持久化&#xff1a;消息存储在磁盘&#xff0c;所以消息不会丢失 2.高吞吐量&#xff1a;可以轻松实现单机百万级别的并发 3.扩展性&#xff1a;扩展性强&#xff0c;还是动态扩展 4.多客户端支持&#xff1a;支持多种语言&#xff08;Java、C、C、GO、…

WPF中如何根据数据类型使用不同的数据模板

我们在将一个数据集合绑定到列表控件时&#xff0c;有时候想根据不同的数据类型&#xff0c;显示为不同的效果。 例如将一个文件夹集合绑定到ListBox时&#xff0c;系统文件夹和普通文件夹分别显示为不同的效果&#xff0c;就可以使用模板选择器功能。 WPF提供了一个模板选择…