作用域、解构、箭头函数

作用域

局部作用域

函数作用域(一直 存在)
块作用域(ES6,只有let和const有块级作用域,var没有)

块就是一对大括号,比如{ }、if(){ }、for(…){ }
使用var则失去块级作用域

//例如
for(var i=1;i<=3;i++)
{console.log(i)}
console.log(i);//正确,var定义的i是全局变量

全局作用域

script标签和.js文件的最外层就是所谓的全局作用域,在此声明的变量在函数内部也可访问。
全局作用域声明的变量,任何其他作用域都可访问
注意
1.为window对象动态添加的属性默认是全局的,不推荐!
2.函数中未使用任何关键字声明的变量为全局变量,不推荐!!!
3.尽可能少的声明全局变量,防止全局变量被污染

作用域链

作用域链本质上是底层的变量查找机制
在函数被执行时,会优先查找当前函数作用域中查找变量
如果当前作用域找不到则会依次逐级查找父级作用域直到全局作用域

垃圾回收机制(GC)

JS中内存的分配和回收都是自动完成的。内存在不使用的时候会被垃圾回收器自动回收
但不了解JS的内存管理机制,我们同样非常容易造成内存泄漏(内存无法回收)的情况
不在用到的内存,没有及时释放,就叫做内存泄漏

内存的生命周期

JS环境中分配的内存,一般有如下生命周期
1.内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存
2.内存使用:即读写内存,也就是使用变量、函数等(函数一调用。临时为函数再分配一小块内存,用于运行函数中的局部变量,函数执行完毕,函数中的局部变量就被释放)
3.内存回收:使用完毕,由垃圾回收自动回收不在使用的内存
4.说明:
a)全局变量一般不会回收(关闭页面回收)
b)一般情况下局部变量的值,不用了会被自动回收掉

垃圾回收算法说明

所谓垃圾回收,核心思想就是如何判断内存是否已经不会再被使用了,如果是,就视为垃圾,释放掉
下面介绍两种常见的垃圾回收算法:引用计数法和标记清除法

引用计数法(算法固定,有缺陷被淘汰)

IE采用的引用计数算法,定义“内存不在使用”的标准很简单,就是看一个对象是否有指向它的引用
算法:
1.跟踪记录每个值被引用的次数
2.如果这个值被引用了一次,那么就记录次数1
3.多次引用会累加
4.如果减少一个引用就减1
5.如果引用次数是0,则释放内存

//声明变量,代码运行的时候,就会分配内存,存储对象的内容
//同时,有一个变量指向这个对象,所以这个对象的引用次数为1
let obj={uname:'zzs',gae:20}
//下面的代码意思是让obj2也指向这个对象,所以这个对象的引用次数为2
let obj2=obj
//下面让obj=null ,也就是说obj不再指向对象了,则这个对象的引用次数减1
obj=null
//下面让obj2=null,也就是说obj2不再指向对象了,则这个对象的引用次数减1
obj2=null
//到这里,对象的引用次数为0,则垃圾回收器会自动回收对象占用的内存

引用计数的问题

function fn(){
let o1={}
let o2={}
//给o1增加属性
o1.a=o2;
o2.a=o1
}
fn()
//相互引用,造成对象(o1、o2)的引用次数始终为1,这两个对象占用的内存始终不会释放
//这样就造成了内存的泄漏
标记清除(主流浏览器都在使用)

现在浏览器通用的大多是基于标记清除算法的某些改进算法,总体的思想都是一致的
核心:
1.标记清除算法将“不在使用的对象”定义为“无法达到的对象
2.就是从根部(在js中就是全局对象)出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的
3.那些无法由根部出发触及到的对象标记为不再使用,稍后进行回收

闭包(有了let、const之后应用比较少,应付面试)

概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解:闭包=内层函数+外层函数的变量

function outer()
{
	let a=10 //构成闭包的要素之一,外层函数中得有一个变量
	function fn()
	{
	console.log(a) //构成闭包的要素之二,内存函数中使用外层函数的变量
	}
	fn()
}
outer()


//常用闭包写法(防止全局变量经常被修改,闭包函数中的内部变量不受到全局变量的影响)

function outer()
{
	let a=10 //构成闭包的要素之一,外层函数中得有一个变量
	function fn()
	{
	console.log(a) //构成闭包的要素之二,内存函数中使用外层函数的变量
	}
	return fn
}
let xx=outer() // xx=function fn(){console.log(a)}
xx()  //调用xx 相当于调用了fn  //外层函数使用内部函数的变量a



变量提升

//代码运行的时候,会把函数的声明、创建提升到当前作用域的最开头
//代码运行的时候,会把用var声明变量(let和const声明的变量不会提升)的声明过程(没有赋值过程)提升到最开头(在函数之后)
console.log(a)
fn()
var a=10
function  fn(){
console.log(123)
}

在这里插入图片描述

提升的特点

提升的时候,把函数提升到最前面,其次是用var声明的变量
提升只会把var声明的变量提升到当前作用域的最前面

var a=1000
function fn()
{
var a
console.log(a) //undefined
}
fn()
let和const的提升问题

变量的创建分为三步:创建—>声明—>赋值
var会把创建和声明,提升到最开头
let会把创建提升到最开头(let创建的变量,在声明之前使用是不行的)
let如果在创建之后,声明之前使用,就进入了“暂时性死区”。

let a=100
function fn(){
//这里有一个隐式的创建过程,会提升到当前作用域的最开头,否则将会输出a=100,不能使用外层的a,let a叫声明
console.log(a)
let a=20
}
fn()

在这里插入图片描述

    <script>
        var a = 100
        var a  //只有重新赋值会覆盖,声明不会覆盖
        console.log(a) //100
    </script>

    <script>


        console.log(a)  //先把函数a提升,后续Var a提升,只是声明,没有覆盖,则a还是函数
        var a = 10  //只把声明var a提升到前面
        function a() {    //函数提升到最前面
            console.log(1111)
        }
        console.log(a)  //a=10
        var a = 20
        //提升只是把声明提升了,赋值的位置不变
        console.log(a)   //a=20
    </script>

在这里插入图片描述

函数

函数参数

动态参数
function sum(){
//实参不固定的时候,干脆形参直接不写
//这样的普通函数中有一个固定对象叫arguments(不能出现在箭头函数中),是一个伪数组(不能调用数组方法),本质上是一个对象,保存传递进来的实参
let num=0
for(let i=0;i<arguments.length;i++)
{num=num+arguments[i]}
}


//实参有几个不固定
sum(2,3)
sum(2,3,4,5)
sum(4,1,8,2,9)
}
剩余参数
function fn(a,b,...c)
{
//a接收了4,b接收了1,...c接收了剩余所有实参
console.log(a,b,c)
}


fn(4,1,5,6,2)

在这里插入图片描述

展开运算符(类似剩余参数)

1.在构造数组时,能够将其他数组和字符串展开

let arr1=[3,4]
let arr2=[5,6]
let arr=[100,200,...arr1]  //将arr1展开放到数组arr中

在为函数传递参数的时候,能够将其他数组或字符串展开

let arr3=[2,8,6,5,9]
function fn(...a) //形参中的...是剩余参数
{}
fn(...arr3) //相当于fn(2,8,6,5,9)  实参中的...是展开运算发

在构造字面量对象的时候,能够展开其他对象

let obj1={uname:'zs',age:20}
let obj2={sex:'男',height:180}
//运用,加入obj的属性
let obj={id:100,...obj1....obj2,weight:75}
函数参数的默认值
//如果实参未传入参数,则当undefined处理
function fn(a,b=10)
{
}
fn(3,4) //传递两个参数,优先使用我们传递进去的实参,也就是a=3,b=4
fn(6) //传递了一个参数,则a=6,没有给b传递实参,则b使用默认的10

箭头函数

箭头函数是ES6中的新语法,是新的声明函数的方式,其目的是为了简化函数的写法

语法

箭头函数属于表达式函数,因此不存在函数提升
简化写法:
箭头函数只有一个参数时可以省略圆括号()
箭头函数函数体只有一行代码时可以省略花括号{},并自动作为返回值被返回
箭头函数中没有arguments,只能使用…动态获取实参

//写法
// (形参)=>{函数体}
let fn=(a,b)=>{
console。log(12345)
}

let fn=(x)=>{return x*x}
//简写
let fn=x=>x*x
//箭头函数的使用。例如当作其他函数的参数,举例
setTimeout(()=>{},1000)

//特别注意
let fn=()=>{return {uname:'zs,age:20}}
//简写不能写成let fn=()=>{uname:'zs,age:20} 因为无法分清这个大括号{}是函数的大括号还是对象的大括号
//写成
let fn=()=>({uname:'zs,age:20})//额外价格小括号,以免引起歧义 

箭头函数内部没有自己的this,箭头函数中的this,把它当作普通变量,使用的时候按照作用域去查找

document.querySelector('button').addEventListener('click',function(){
console.log(this) //这里的this是事件源button
})
//换成箭头函数
document.querySelector('button').addEventListener('click',()=>{
console.log(this)  //这里的this为普通变量,函数中没有则到全局作用域去查找
})

解构

数组的解构

解构赋值
解:展开
构:结构的意思(在js中有结构的变量是数组和对象)
赋值:把一个值赋值给一个变量
总的来说:就是展开数组或对象,将里面的值取出,赋值给一些变量

//数组的解构
//相当于将几个值赋值给几个变量
let [a,b,c,d]=[1,2,3,4]  //变量和值的数量不对等的时候,按顺序赋值
//另一个写法
let [,a,,b]=['老段''琪琪‘,'小军','小名']
//为了给变量a赋值琪琪。变量b赋值小名,又不想创建多余的变量,则可以用逗号代替
let [a,[b,c,d]]=[1,[3,4,5]]  //前后对应,严格保证顺序


对象的解构(用的超级多)

对象的解构不看顺序和顺序无关,
保证 变量名===对象的键 即可实现解构

let {uname,sex}={uname:'zs',age:20.sex:'男'}
//需要什么变量,写什么变量名即可

let person={
uname:'zs',
age:34,
dog:{dname:'旺财',dage:3},
cat:{cname:'小花',cage:2}}

let {uname,dog:{dname}}=person //前后对应

//举例,在传参的时候直接结构出来
function fn({age}){console.log(age)}
fn(person)
对象解构时为变量定义别名
let age=20;
//不能重复定义同一个名字的变量
let {uname,age:其他的名字}={uname:'zs',age:100}

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

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

相关文章

Semantic human matting

1.introduction 数据集包括&#xff0c;时尚模特数据集&#xff0c;超过18.8w张模特图&#xff0c;从中选出35311张图片&#xff0c;DIM数据集&#xff0c;仅包含人类的图像&#xff0c;202个前景图像&#xff0c;背景来自coco数据集和互联网&#xff0c;背景图不含人类&#x…

SpringBoot整合MyBatis实现增删改查

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容: SpringBoot整合MyBatis实现增删改查 📚个人知识库: Leo知识库,欢迎大家访…

【问题解决】| 关于torch无法使用GPU的一些实验探索,思考

文章目录 1 研究背景2 问题解决2.1 问题一&#xff0c;这两个版本分别是怎么得到的&#xff1f;2.2 问题二&#xff0c;Windows下安装CUDA Tookit 是必须的吗&#xff1f;2.3 问题三&#xff0c;驱动版本必须大于等于运行时版本吗&#xff1f;2.4 问题四&#xff0c;只运行pip …

【大厂AI课学习笔记NO.56】(9)模型评测

作者简介&#xff1a;giszz&#xff0c;腾讯云人工智能从业者TCA认证&#xff0c;信息系统项目管理师。 博客地址&#xff1a;https://giszz.blog.csdn.net 声明&#xff1a;本学习笔记来自腾讯云人工智能课程&#xff0c;叠加作者查阅的背景资料、延伸阅读信息&#xff0c;及学…

微信小程序证书评级导致接口无法访问问题

微信小程序的ssl证书到期后&#xff0c; 更换了免费的ssl证书&#xff0c; 是在freessl网站申请的&#xff0c; 配置完了&#xff0c;后台可以访问https网页&#xff0c;但是小程序还是无法访问&#xff0c; 开始没有怀疑是https证书的问题&#xff0c; 调适了好长时间的代码&a…

前后端分离vue+nodejs高校体育运动会比赛系统08fv2-python-php-java

实现了一个完整的高校体育运动会比赛系统系统&#xff0c;其中主要有运动项目模块、学生模块、项目类型模块、用户表模块、token表模块、关于我们模块、收藏表模块、公告信息模块、留言板模块、运动论坛模块、配置文件模块、裁判员模块、比赛成绩模块、比赛报名模块、关于我们模…

9、taocms代码审计

一、XSS 1、DOM型xss 限制 无复现 payload: aa)alert(1)( 触发的参数&#xff1a;name代码 根据路由找到对应的文件&#xff0c;在api.php里接受全局变量action&#xff0c;最终赋值给$m,判断 如果$m不在数组就结束&#xff0c;新建方法复制给$model。检查类的方法是否存…

ctf_show笔记篇(web入门---爆破)

爆破 21&#xff1a;直接bp抓包跑字典&#xff0c;需base64加密 22&#xff1a;可用工具跑也可用浏览器找还可以用网上做好的域名查找去找 23&#xff1a;此题需跑脚本已经附上自写脚本 最后跑出来六个答案一个一个尝试得到答案为3j import hashlibm "0123456789qwert…

安卓之ContentProvider的应用场景以及优劣分析

摘要 本文旨在对Android开发中的ContentProvider进行深入探讨。ContentProvider是Android系统中四大组件之一&#xff0c;主要用于在不同的应用程序之间共享数据。本文首先对ContentProvider进行概述&#xff0c;然后分析其应用场景&#xff0c;接着对其优势和劣势进行分析&…

Linux设备模型(十一) - platform设备

一&#xff0c;platform device概述 在Linux2.6以后的设备驱动模型中&#xff0c;需关心总线、设备和驱动这3个实体&#xff0c;总线将设备和驱动绑定。在系统每注册一个设备的时候&#xff0c; 会寻找与之匹配的驱动&#xff1b;相反的&#xff0c;在系统每注册一个设备的时…

开发者38万+,鸿蒙开发岗为何却无人敢应聘?

鸿蒙校园公开课已走进135家高校&#xff0c;305所高校学生参与鸿蒙活动&#xff0c;286家企业参加鸿蒙生态学堂&#xff0c;38万开发者通过鸿蒙认证。 居上华为官方是说有通过鸿蒙开发者认证的已有38万。具体有多少开发者并没有明确表示。除此之外还有200家头部应用加速鸿蒙原…

【Golang切片】

切片 切片的引入内存分析切片的定义切片的遍历切片注意事项 切片的引入 【1】切片&#xff08;slice&#xff09;是golang中一种特有的数据类型 【2】数组有特定的用处&#xff0c;但是却有一些呆板&#xff08;数组长度固定不可变&#xff09;&#xff0c;所以在Go语言的代码…

面试题VUE篇

文章目录 Vue 的核心是什么/请简述你对 vue 的理解请简述 vue 的单向数据流槽口请简述Vue 常用的修饰符有哪些1. 普通修饰符2. 事件修饰符3. 键盘修饰符4. 系统修饰符 v-text 与{{}}与 v-html 区别v-on 可以绑定多个方法吗Vue 循环的 key 作用什么是计算属性Vue 单页面的优缺点…

最新版阿里云Linux CentOS7 ecs-user用户安装Mysql8详细教程(超简单)

经过两天的踩坑后&#xff0c;终于成功安装&#xff0c;并找到了最快捷的安装方式。接下来就由我来给大家介绍不踩坑安装大法&#xff01; 一、下载Mysql 首先前往Mysql官网下载 MySQL官方下载地址 第一步&#xff0c;选择安装包&#xff0c;这是最关键的一步&#xff0c;选错安…

进程与线程:通过实际生活来解析计算机的基本运作单位

进程与线程 进程与线程&#xff1a;详细解析计算机的基本运作单位1. 进程&#xff1a;独立的执行环境1.1 进程的特点&#xff1a; 2. 线程&#xff1a;轻量级的执行单元2.1 线程的特点&#xff1a; 3. 区别和联系4. 表格 进程与线程&#xff1a;详细解析计算机的基本运作单位 在…

AsConvSR | NTIRE2023-RTSR-Track1冠军方案

编辑 | Happy 首发 | AIWalker 链接 | https://mp.weixin.qq.com/s/p9u6RYkd37MmN12rUCMCuQ 前段时间&#xff0c;NTIRE2023各个竞赛落下帷幕&#xff0c;近期各个冠亚军方案提出者也在逐步公开方案细节。今天给大家概要介绍一下"RTSR-Track1"赛道冠军方案&#xff…

【Leetcode每日一题】前缀和(难度⭐)(25)

1. 题目解析 题目链接&#xff1a;DP34 【模板】前缀和 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于计算题目所给区间数组元素和返回即可。 2. 算法原理 为了提高计算效率&#xff0c;我们可以预先计算出一个「前缀…

【NDK系列】Android tombstone文件分析

文件位置 data/tombstone/tombstone_xx.txt 获取tombstone文件命令&#xff1a; adb shell cp /data/tombstones ./tombstones 触发时机 NDK程序在发生崩溃时&#xff0c;它会在路径/data/tombstones/下产生导致程序crash的文件tombstone_xx&#xff0c;记录了死亡了进程的…

Appium移动端自动化测试-(Java)

目录 环境搭建ADB调试工具adb构成adb工作原理adb常用命令电脑连接多个设备跟模拟器使用adb包名与界面名的概念如何获取包名和界面名文件传输获取app启动时间获取手机日志其他命令 Appium全自动化测试框架&#xff08;python&#xff09;冲错了序言 环境搭建Appium客户端安装App…

【洛谷学习自留】p5707 上学迟到

解题思路&#xff1a; 1.先用给出的时间和速度&#xff08;如果无法整除&#xff0c;则时间加一&#xff09;&#xff0c;计算出时间&#xff08;分&#xff09;&#xff0c;然后将时间加上10分钟。 2.创建一个计时器&#xff0c;设置一个日期&#xff0c;保证时分秒部分&#…