JavaScript 进阶A(作用域、闭包、变量和函数提升、函数相关只是、数组解构、对象解构、构造函数

1.作用域

作用域主要分为:局部作用域和全局作用域。

局部作用域又分为:函数作用域和块作用域

  • 函数作用域:在函数中定义的变量只能在函数内部使用,外部无法访问
  • 块作用域:被大括号{}包起来的代码块,在这个代码块中定义的变量就生存在块作用域内

 全局作用域:全局作用域可以被其他作用域访问

作用域链

作用域链就是变量查找的机制,在函数被调用的时候,会优先查找函数作用域内的变量。如果找不到再去依次向外层父作用域查找。
如果被调函数作用域内有与外部变量同名变量,优先调用函数作用域内部变量

作用域之间的关系:子作用域可以访问父作用域,父作用域不可访问子作用域

 2.闭包

我们来看一个简单的闭包实例

function outter(){
    let a =0
    function inner(){
        a++
        console.log(a)
    }
    return inner
}

let key = outter()
//实际上就是 key = inner 因为outter()最后的返回值是inner

key()
//调用一次就执行一次inner()函数

这是一个简单的计数器的例子,当我们使用key接收inner的值的时候。其实就是执行了一边outter函数然后把函数的返回值赋给key。此时的key()就是执行inner函数。

按理来说变量a会随着outter函数的结束而销毁。但是实际情况却并不是,我们通过key依旧可以访问这个变量。这里就要讲一下js的垃圾回收机制了。

js的垃圾回收机制是根据变量是否被引用而决定是否销毁它。因为在inner函数中我们通过console.log引用了外部的变量a。这就导致了内部的函数引用了外部的变量。虽然外部函数结束了,但是由于这个变量依旧被引用,所以变量得以保存

详细的过程:

1.当outter函数被执行的时候,会创建一个局部变量a
2.当inner函数被定义的时候会捕获其所在的词法环境
3.outter函数执行结束,正常情况是a被销毁,但是由于inner函数的引用,让a得以保存
4.当inner函数执行的时候仍然可以访问a,因为闭包保留了a

至于为什么不直接使用变量去实现计数器的效果,是因为闭包会把一个变量变为私有变量。正常的访问是无法访问这个变量的。只有我们通过inner函数调用的时候才会访问这个变量。这在一定程度上提升了安全性。

3.变量和函数提升

变量提升

变量的声明有三种方式:1.let  2.const  3.var

前两种我们经常会用到,但是第三种我们在之前都没怎么用过。

其实let和var本质上都是差不多的,唯一的区别在一var会存在“变量提升”

变量提升就是允许变量在声明之前被访问

我们来看两个案例:

案例1

console.log(num)

let num =10


案例2

console.log(num)

var num =10



结果:案例一报错。案例二打印undefined

通过这个我们可以很明确的发现,使用var声明的变量可以在声明语句前被访问,但是访问的结果是undefined,变量在未赋值之前访问结果是undefined。这也就说明了:变量提升只会提升变量的定义,不会提升赋值。

案例2的代码就相当于:

let a
console.log(a)
a=10

我们应该避免使用var

函数提升

函数提升和变量提升基本上一样,函数提升就是把当前作用域的函数声明提升到最前面。

我们在之前的代码中可能都会把函数声明来写到后面。

按照之前的思路来说,应该是先声明在使用。但是函数自己的定义就会有提升的效果。也就是说函数默认有函数提升。

我们之后在编写代码的时候如果有函数需要单独的写出来,我们建议写在最前面。

4.函数相关(参数、箭头函数

函数参数

动态参数

我们在编写代码的时候一般都会提前写好有几个参数,但是有的时候我们并不能确定我这个函数需要几个参数。这个时候再编写函数的代码的时候就会非常困难。

但是我们有一种方法可以解决这个问题:函数内置的arguments伪数组。

 function fn(){
      console.log(arguments.length)
      console.log(arguments[0], arguments[1], arguments[2])
      console.log(typeof arguments[0], typeof arguments[1], typeof arguments[2])
  }
  fn(1,1.1,"Www")

看这段代码,我的函数在定义的时候是没有声明形参的,但是我调用的时候却传入了三个实参。

然后我通过arguments这个函数内置的伪数组得到了这三个参数。

arguments是函数内置的伪数组,它可以存储调用函数的时候传入的参数。即使函数定义了形参我依旧可以通过arguments获取这个形参

剩余参数

剩余参数:我们在传参的时候一般都是一一对应的传参,如果传递的实参数量大于形参,剩余的没有对应的参数就是剩余参数。我们可以把这些剩余参数表示为一个真数组

下面看案例来理解:

 function fn(num,...arr){
      console.log(num);
      console.log(arr);
  }
  fn(1,2,3,4,5,7)

最后输出num是1,arr是一个数组,数组包含2,3,4,5,7

这个arr就是一个剩余参数构成的数组,一般来说我们都会把剩余参数写在参数列表的后面。

展开运算符:...数组 -》可以把数组的所有元素拿出来
假设有一个数组arr=[1,2,3,4,5,6,7] 则 ...arr = 1,2,3,4,5,6,7(不是字符串

箭头函数

箭头函数基本形式

(参数)=>{函数体}

1.如果参数只有一个 :可以省略参数的小括号: 参数=>{函数体}

2.如果函数体只有一条语句:可以省略大括号: (参数)=>语句  并且这个语句的结果就是返回值

箭头函数的this --- 继承父级的this

一个对象里面的方法(普通函数)的this指向这个对象,因为是对象调用了这个方法
一个对象里面的方法(箭头函数)的this指向window,因为箭头函数的this继承了对象的this

数组解构

作用:快速批量赋值

用法1.

arr = [1,2,3,4,5,6,7]

const [a,b,c,d,e,f,g] = arr 或者 const [a,b,c,d,e,f,g] = [1,2,3,4,5,6,7]

用法2.

有两个变量,想交换它们的值:[a,b] = [b,a]

注:const [a,b,c] = [1,2]这种情况下c是undefined
const [a,b] = [1,2,3]这种情况下会舍去多余的
可以使用剩余参数防止丢失:const[a,b,...c] = [1,2,3,4,5,6,7,8,9] 这种情况a1,b2,c是数组

对象解构

对象解构的作用和数组结构一样

我们先来回顾以下对象

对象名={对象内容},对象内容可以是变量或者函数,变量称为属性,函数称为方法。中间使用逗号隔开

obj ={
    name:"www",
    age:11,
    outer:function(){
        console.log(this.name,this.age)    
        }
}

const {name,age,outer} = obj

console.log(name,age)
outer()

具体使用没什么区别,然后要注意的是数组使用[]对象使用{}
方法结构出来可以调用它。但是outer是不能输出我们想要的内容的,主要是解构出来之后调用者从obj变成了window。

变量的名字要和属性名一致

如果想让变量不和属性一个名字可以使用const{name:aaa}这种方式让name变成aaa

 构造函数

我们首先讲一下new关键字,这个关键字用于创建一个空对象
这个空的对象里面什么都没有,我们有两个方法为这个对象添加属性或者方法
1.new 构造函数()
2.new一个对象,通过对象.属性/方法添加

这是通过构造函数:

构造函数的作用就是创建和初始化对象。他需要使用new关键字调用

下面是一个简单的构造函数:

function student(stu_name,stu_age,stu_gender,stu_add){
        this.name=stu_name;
        this.age=stu_age;
        this.gender=stu_gender;
        this.add=stu_add;
    }
    const stu1= new student("xxx",11,"nan","001100")
    console.log(stu1)

我们首先声明了一个构造函数,这个函数接收四个参数

通常来说,这个函数里面的this指的是window。但是通过new关键字调用构造函数会把new关键字创建的新对象绑定到构造函数的this。
我们只需要记住通过new关键字调用构造函数,构造函数的this指向new创建的对象
其实我们在构造函数里面打印一下this就能知道this指向的是谁了。上面的例子里打印this会打印出student

这是通过手动添加:

我们需要先创建一个空的对象:const obj = new Object()

然后obj.属性/方法    添加属性或者方法

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

StableDiffusion本地部署 3 整合包猜想

本地部署和整合包制作猜测 文章目录 本地部署和整合包制作猜测官方部署第一种第二种 StabilityMatrix下载整合包制作流程猜测 写了这么多python打包和本地部署的文章,目的是向做一个小整合包出来,不要求有图形界面,只是希望一键就能运行。 但…

‘ts-node‘ 不是内部或外部命令,也不是可运行的程序

新建一个test.ts文件 let message: string = Hello World; console.log(message);如果没有任何配置的前提下,会报错’ts-node’ 不是内部或外部命令,也不是可运行的程序。 此时需要安装一下ts-node。 npm install

(done) MIT6.S081 Interrupts Lecture 学习笔记

url: https://mit-public-courses-cn-translatio.gitbook.io/mit6-s081/lec09-interrupts/9.1-memory-in-real-os 9.1 真实操作系统内存使用情况 今天课程的内容是中断。但是在具体介绍中断之前,我想先回顾一下上周一些有趣的内容。因为上周的课程主要是讲内存&…

40岁开始学Java:Java中单例模式(Singleton Pattern),适用场景有哪些?

在Java中,单例模式(Singleton Pattern)用于确保一个类只有一个实例,并提供全局访问点。以下是详细的实现方式、适用场景及注意事项: 一、单例模式的实现方式 1. 饿汉式(Eager Initialization) …

【计算机网络基础】-------计算机网络概念

1.什么是计算机网络 定义: 图解: 2.最简单的计算机网络 其中: 结点可以是计算机、集线器、交换机、路由器等链路可以是有线链路、无线链路 2.1集线器 2.2交换机 3.互连网(internet)与 路由器 路由器 与 家用路由…

Qt 自带颜色属性

Qt 系统自带颜色如下: enum GlobalColor {color0,color1,black,white,darkGray,gray,lightGray,red,green,blue,cyan,magenta,yellow,darkRed,darkGreen,darkBlue,darkCyan,darkMagenta,darkYellow,transparent};对应颜色如下: color0: 这是自定义颜色…

数据结构(初阶)(七)----树和二叉树(前中后序遍历)

实现链式结构的二叉树 实现链式结构的二叉树遍历前序遍历中序遍历后序遍历 节点个数叶子节点个数⼆叉树第k层结点个数⼆叉树的深度/⾼度查找值为X的节点二叉树的销毁 层序遍历判断二叉树是否为完全二叉树 ⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。 通常…

哔哩哔哩IT私塾python爬虫视频教程中的项目文件

视频链接: Python课程天花板,Python入门Python爬虫Python数据分析5天项目实操/Python基础.Python教程_哔哩哔哩_bilibili 视频教程中要访问的链接: 豆瓣电影 Top 250 httpbin.org seo推广公司网站模板_站长素材 Examples - Apache ECharts WordCloud…

实验:k8s+keepalived+nginx+iptables

1、创建两个nginx的pod,app都是nginx nginx1 nginx2 2、创建两个的pod的service 3、配置两台keepalived的调度器和nginx七层反向代理,VIP设置192.168.254.110 keepalived调度器master keepalived调度器backup 两台调度器都配置nginx七层反向代理&#…

【Cadence仿真学习笔记】ADS Dynamic Link报错model is reserved的解决办法

首先创建好原理图 创建symbol 在library manager下就会出现symbol了 在Cadence的CIW窗口中运行ADS dynamic link 打开ADS后,创建对应的cellview 加入控件OPTIONS 加入网表netlist 这个时候的Netlist没有路径 点击加载symbol 把原来的netlist include删掉…

【星云 Orbit • STM32F4】06. 串口密码:USART 数据传递

1. 引言 STM32F407是一款高性能的微控制器,具有丰富的外设和强大的处理能力。串口(USART)是STM32F407的重要外设之一,广泛应用于数据通信、调试和控制等领域。本教程旨在帮助小白从零开始,手动配置STM32F407的串口功能…

Win32 C++ 电源计划操作

CPowerCfgUtils.h #pragma once#include <Windows.h> #include <powrprof.h>// https://learn.microsoft.com/zh-cn/windows/win32/api/powrprof/?sourcerecommendations//节能 //DEFINE_GUID(GUID_MAX_POWER_SAVINGS, 0xA1841308, 0x3541, 0x4FAB, 0xBC, 0x81, …

MySQL—使用binlog日志恢复数据

一、binlog日志恢复数据简介 在 MySQL 中&#xff0c;使用二进制日志&#xff08;binlog&#xff09;恢复数据是一种常见的用于故障恢复或数据找回的方法。以下是详细的使用步骤&#xff1a; 确认 binlog 已启用&#xff1a;首先需要确认 MySQL 服务器已经启用了二进制日志功…

基于springboot+vue实现的宠物救助及领养平台(源码+L文+ppt)43-21

摘 要 宠物救助及领养平台是一个专注于宠物保护和幸福的在线平台。它致力于连接那些需要帮助的宠物与愿意给予它们关爱的家庭。通过这个平台&#xff0c;人们可以报告丢失的宠物、寻求救助资源&#xff0c;以及浏览可领养的宠物信息。该平台不仅提供了一个渠道&#xff0c;让…

人大金仓国产数据库与PostgreSQL

一、简介 在前面项目中&#xff0c;我们使用若依前后端分离整合人大金仓&#xff0c;在后续开发过程中&#xff0c;我们经常因为各种”不适配“问题&#xff0c;但可以感觉得到大部分问题&#xff0c;将人大金仓视为postgreSQL就能去解决大部分问题。据了解&#xff0c;Kingba…

【Java分布式】Nacos注册中心

Nacos注册中心 SpringCloudAlibaba 也推出了一个名为 Nacos 的注册中心&#xff0c;相比 Eureka 功能更加丰富&#xff0c;在国内受欢迎程度较高。 官网&#xff1a;https://nacos.io/zh-cn/ 集群 Nacos就将同一机房内的实例划分为一个集群&#xff0c;一个服务可以包含多个集…

派可数据BI接入DeepSeek,开启智能数据分析新纪元

派可数据BI产品完成接入DeepSeek&#xff0c;此次接入标志着派可数据BI在智能数据分析领域迈出了重要一步&#xff0c;将为用户带来更智能、更高效、更便捷的数据分析体验。 派可数据BI作为国内领先的商业智能解决方案提供商&#xff0c;一直致力于为用户提供高效、稳定易扩展…

【漫话机器学习系列】110.线性可分(Linearly Separable)

线性可分与线性不可分的概念详解 1. 引言 在机器学习和模式识别领域&#xff0c;分类问题是一个重要的研究方向。在分类任务中&#xff0c;我们通常需要将不同类别的数据点分开&#xff0c;而如何进行分割是一个关键问题。线性可分&#xff08;Linearly Separable&#xff09…

架构师面试(九):缓存一致性

问题 关于【数据库和缓存】一致性&#xff0c;下面哪几项是在线上生产环境中相对合理的处理方式&#xff1f; A. 对于查询操作&#xff0c;先查缓存&#xff0c;如果为空则查 DB&#xff0c;然后将数据带入缓存&#xff1b; B. 对于插入操作&#xff0c;只写 DB 即可&#…

LearnOpenGL之Shader编程用算法绘画

———————————————————— 前序 ——————————————————— AndroidLearnOpenGL是本博主自己实现的LearnOpenGL练习集合&#xff1a; Github地址&#xff1a;GitHub - wangyongyao1989/AndroidLearnOpenGL: OpenGL基础及运用 系列文章&#xff…