前端学习笔记 | JS进阶

一、作用域

1、局部作用域

(1)函数作用域

(2)块作用域

let和const会产生块作用域  ,而var不会产生块作用域

2、全局作用域

script标签和js文件的【最外层】变量

3、作用域链

本质:底层的变量查找机制

4、JS垃圾回收机制(GC)

(1)内存的生命周期

  • 内存分配
  • 内存使用
  • 内存回收

(2)算法说明

  • 引用计数法:嵌套循环容易使内存泄漏
  • 标记清除法:从全局出发,找不到就回收

5、闭包

闭包=内存函数+外层函数的变量

作用:外部访问局部变量、局部函数

function outer(){let i=1return function(){console.log(i)}
}
const fun = outer()
fun()

应用:实现数据的私有,外部无法直接修改变量

注:容易引起内存泄漏

6、变量提升

 JS的缺陷(使用var的时候):代码执行前会将所有的var声明的变量提升到当前作用域的最前面,只提升变量声明,不提升变量声明——不建议

二、函数进阶

1、函数提升

2、函数参数

(1)动态参数(不推荐)

数组arguments:不管拿多少变量,都能获取到。

方法:不用形参,函数内部直接使用arguments

缺点:伪数组

(2)剩余参数(推荐)

arr获取的是多余的实参,是真数组,可以使用数组方法

function getSum(a,b,...arr)

...arr是展开数组

3、箭头参数

(1)特点

替代匿名函数

属于表达式函数,不存在函数提升

(2)基本语法

//基本写法
const fn = () =>{ }//只有一个形参的时候可以省略小括号
const fn= x => { }//只有一个形参的时候可以省略大括号
const fn= x => console.log(x)//只有一行代码可以省略return
const fn= x => return x+x
const fn= x => x+x//箭头函数可以直接返回一个对象
const fn= (unname) => ({uname:uname})

(3)箭头函数参数

普通函数有arguments,箭头函数没有

(4)箭头函数this

this指的是对象

箭头函数的this指向上一层作用域的this

三、解构赋值

1、数组解构

将数组单元值快速批量赋值给变量的简洁语法

const arr = [100,60,80]
const [max,min,avg ] =arr
等同于
//const max=arr[0]
//const min=arr[1]
//const avg=arr[2]

典型应用:交换两个变量的值

let a=1
let b=2
;[b,a]=[a,b] //这里必须加分号

补充:必须加;的情况

  • 立即执行函数
(function(){})();
  • 数组的时候:数组开头的
const str='pink';
[1,2,3].map(function(item)){}

2、对象解构

将对象属性和方法快速批量赋值给变量的简洁语法

(1)基本

const[{uname,age}]=obj

(2)多级对象

复合对象需要在前面加一个名字

const pig={name:'佩奇'family:{mother:'猪妈妈'father:'猪爸爸'sister:'乔治'}age:6
}const [{name,family:{mother,father,sister}}]=pig

 四、数组forEach遍历和filter筛选

1、forEach语法

(1)语法

const arr=['red','green','blue']
arr.forEach(function(item,index){console.log(item) console.log(index)
})

(2)作用

主要遍历数组——加强版for循环

和map(返回数组)的区别,不返回值

2、filter方法

(1)语法

const arr=[10,20,30]
arr.filter(funtion(item,index){return item>=20
})

(2)特点

用于筛选数组

函数返回生成一个新数组

 五、深入对象

1、创建对象三种方式

(1)通过字面量

const o={name:'佩奇'
}

(2)利用new Object创建对象

const o=new Object({name:'佩奇'})
console.log(o)

(3)利用构造函数创建对象

2、构造函数

(1)是什么

特殊函数,用于初始化对象

(2)语法

function pig(name){this.name=name
}
const peppa=new Pig('佩奇') //实例化

3、实例成员&静态成员

(1)实例成员

构造函数创建的对象叫实例对象,实例对象的属性和方法为实例成员

(2)静态成员

构造函数的属性和方法被称为静态成员

  • 静态成员只能构造函数来访问
  • 静态方法中的this指向构造函数

4、内置构造函数

(1)Object 

  • Object.keys(o) 
  • Object.values(o) 
  • Object.assign(新对象,原对象) 
const o={name:'佩奇',age:6}
Object.keys(o) //返回数组['uname','age']
Object.values(o) //返回数组['佩奇','6']

(2)Array

  • forEach
  • filter
  • map
  • join

  • reduce 返回累计处理结果,经常用于求和
arr.reduce(function(上一次值,当前值){},初始值)

如果需要累加的是对象数组,初始值必须写0

  • find

找出符合的对象

const arr=[
{name:'小米',price:1999},
{name:'华为',price:3999}
]const mi=arr.find(function(item)){return item.name==='华为'
}//返回{name:'小米',price:1999}
  • every

  • some
  • from

把伪数组转换成真数组,可使用pop、push等

  • ...

(3)String

  • length
  • split('分隔符')  分割字符串
  • substring(需要截取的第一个字符的索引[,结束的索引号])  窃取字符串
  • startwith(检测字符串[,检测位置索引号]) 从索引值搜索是否以目标字符串开头
  • endwith(检测字符串[,检测位置索引号])  从索引值搜索是否以目标字符串结束
  • includes(搜索的字符串[,检测位置索引号])  判断是否包含  
  • ... 

(4)Number

  • toFixed(保留位数) 让数字指定保留的位数,默认整数

 六、深入面向对象

1、编程思想

  • 面向过程:面向函数
  • 面向对象
    • 封装性
    • 继承性
    • 多态性

2、构造函数

优点好用,缺点浪费内存——e.g一个对象相同方法但是不等

this指向实例化对象

3、原型对象prototype

能够利用原型对象实现方法共享——原型对象的函数和构造函数都指向实例化对象(this)

公共属性写在构造函数里

公共方法写在原型对象里

function Star(uname,age){this.uname=unamethis.age=age
}
Star.prototype.sing=function(){}

4、 constructor属性

指向原型对象的构造函数

prototype和__proto__均有

5、对象原型_proto_

对象都有一个属性_proto_指向构造函数的prototype原型对象

  • JS非标准属性
  • [[prototype]]和__proto__意义相同
function Star(){}
const ldh =new Star()
console.log(ldh.__proto__ === Star.prototype) //true

6、原型继承

const person={eyes:2,head:1
}
function Woman(){
}Woman.prototype=person
Woman.prototype.constructor=Woman

缺点:继承同一个person,新加方法会有问题

=>用构造函数的写法

7、原型链

基于原型对象的继承使得不同构造函数的原型对象关联在一起

什么是原型链?——一种查找规则:为对象成员查找机制提供一个方向

8、instanceof 

作用:判断对象属不属于原型链上

const ldh=new person()
console.log(ldh instanceof person) //true
console.log(ldh instanceof Object) //true

七、 模态框封装(案例)

1、modalBox 模态框属性

2、(打开模态框)设置open挂载点,页面显示模态框是在open里面

3、(关闭模态框)在open中添加关闭的绑定事件close

注:BUG-会打开多个——先判断,有就移除,没有就添加

box&&box.remove() //逻辑中断,有box则后面不执行,无则执行box.remove()

 八、深浅拷贝

1、深浅拷贝(只针对引用类型)

(1)浅拷贝——简单数据类型拷贝值,引用数据类型拷贝地址

  • 拷贝对象:Object.assign(新对象,旧对象) | 展开对象{...obj}
    • 缺点:复杂对象拷贝会出现问题
  • 拷贝数组 :Array.prototype.concat() | 展开数组[...arr]

(2)深拷贝——拷贝的是对象不是地址

  • 方法1:通过递归(=自己调自己)实现深拷贝
//递归函数
function getTime(){document.querySelector('div').innerHTML= new Date().toLocalString()setTimeout(getTime,1000)
}
getTime()
//深拷贝的方法——做到新对象不会影像旧对象
//1、运用函数递归的方法
//2、如果是普通的,则直接赋值;遇到数组,需要再次调用递归函数。遇到对象,同样再次调用递归函数。
//3、先Array后对象function deepCopy(newObj,oldObj){for (let k in oldObj){if (oldObj[k] instanceof Array){newObj[k]=[] deepCopy(newObj[k],oldObj[k])}else if(oldObj[k] instanceof Object){newObj[k]={}deepCopy(newObj[k],oldObj[k])}else{newObj[k]=oldObj[k]}}
}
  • 方法2:利用lodash
//1、引用lodash.min.js
<script src="./lodash.min.js"></script>
//2、用_cloneDeep(拷贝对象)方法进行深拷贝
<script>const obj={uname:'pink',age:18,hobby:['乒乓球','足球'],family:{baby:'小pink'    }
}const o =_.cloneDeep(obj)
</script>
  • 方法3:利用JSON
//利用JSON.stringify()把JSON转换为字符串
//JSON.parse可以将字符串转换为对象//因为通过对象转换成字符串再转为对象,和原来的对象已经不一样了,修改新对象不会被影响
const o=JSON.parse(JSON.stringify(obj))

九、 异常处理

1、throw 抛异常

//会自动抛出异常并中断程序
//经常配合Error使用function counter(x,y){if(!x || !y){throw new Error("没有参数传递过来")}return x+y
}
counter()

2、try/catch/finally 捕获异常

//可能发生错误的代码,要写到try
//拦截错误,提示浏览器提供的错误信息,但不中断程序的执行function fn(){try{const p=document.querSelector('.p')p.style.color='red'}catch(err){console.log(err.message)throw new Error("你看看,选择器错误了吧")}finally{//finally 不管你程序对不对,一定会执行的代码alert("执行")}
}

3、debugger

打断点——可以直接跳转到改行代码调试

十、处理this

1、this指向

(1)普通函数的指向:谁调用指向谁

//1、指向window
(1)
console.log(this) //指向window
(2)
function fn (){console.log(this)
}  //指向window
(3)
setInterval(function(){console.log(this)
},1000) //指向window
(4)
<button>点击</button>
document.querySelector('button').addEventLisener('click',function(){console.log(this)
}) //指向window//2、指向对象
const obj={sayHI:function(){console.log(this)
}
}
obj.sayHI() //指向obj

(2)箭头函数的指向

与普通函数不同,箭头函数this不受调用方式的影响

箭头函数不存在this,沿用的是上一级的

  • 不适用:构造函数,原型函数,dom事件函数等等
//箭头函数中断this为函数声明函数的this一致
const user={name:'小明'walk:()=>{console.log(this)}
}
user.walk() //指向window

!!!注:原型对象最好不 要用箭头函数,否则this不指向实例对象

2、改变this

(1)call() - 了解

调用函数,同事只当被调用函数的this的值

fn.call(thisArg,arg1,arg2,...)

const obj={uname:'pink'
}
function fn (x,y){console.log(this)//指向windowconsole.log(x+y)
}  fn.call() //单纯调用fn,指向window
fn.call(obj,1,2) //调用fn,改变this,指向obj

(2)apply() -理解

fn.call(thisArg,[argsArray]) 第二个参数必须是数组

const obj={uname:'pink'
}
function fn (x,y){console.log(this)//指向windowconsole.log(x+y)
}  
fn.call(obj,[1,2])//指向obj,打印3

使用场景:求数组的最大值

1、用数组遍历

2、扩展运算符

Math.max(...[arr])

3、用apply方法

Math.max/min.apply(Math/null,数组名)

//传统写法
const max = Math.max(1,2,3) 
console.log(max)//数组求最大值
const arr=[1,2,3]
const max = Math.max.apply(Math,arr)
const min = Math.min.apply(null,arr)

(3)bind()

call()、apply() 会调用函数,但bind()不会调用函数

会改变函数内部this指向

返回值是一个函数,这个函数的this是更改的obj

const obj={age:18    
}function fn(){console.log(this)
}const fun=fn.bind(obj)
fun() //打印obj对象

应用:有一个按钮,点击立马禁用,2s后开启

<button>按钮</button>
const btn=document.querySelector('.button')
btn.addEventListener('click',function(){this.disabled=truewindow.setTimeout(function(){// this.disabled=false //无法打开按钮//btn.disabled=false //可以打开按钮},2000)//或者window.setTimeout(function(){// this.disabled=false //无法打开按钮//btn.disabled=false //可以打开按钮}.bind(btn),2000)//或者window.setTimeout(function(){// this.disabled=false //无法打开按钮//btn.disabled=false //可以打开按钮}.bind(this),2000) //上一层的this指向btn//或者window.setTimeout(=>{this.disabled=false //可以打开按钮,箭头函数没有this,沿用上一层的this},2000) //上一层的this指向btn})

(4)改变this的三种方法及区别(面试常考)

 十一、性能优化

1、防抖 debounce

(1)特点

  • 单位时间内,频繁触发事件,只执行最后一次
  • 王者回城,只要被打断,就需要重新来

(2)语法:_.debounce(fun,时间) 

(3)使用场景

  • 搜索框搜索输入,只需要用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测

(4)案例

要求:鼠标在盒子上移动,里面的数字就会变化+1

const box=document.querySelector('.box')
let i=1
function mousemove(){box.innerHTML=i++
}
box.addEventListener('mousemove',mousemove) //数字变化很快

(改造:不是移动1像素就+1)
方法1、lodash提供的防抖函数 _.debounce(func,[wait=0],[option=])

<script src="./lodash.min.js"></script>
const box=document.querySelector('.box')
let i=1
function mousemove(){box.innerHTML=i++
}box.addEventListener('mousemove',_.debounce(mousemove,500))

方法2、手写一个防抖函数来处理(面试常考)

//核心:利用setTimeout进行实现
//1、声明定时器变量
//2、每次鼠标移动(事件触发)就判断是否有定时器,如果有就先清除定时器
//3、没有就开启定时器,存入到定时器变量里面
//4、定时器里面写函数调用const box=document.querySelector('.box')let i=1function mousemove(){box.innerHTML=i++
}function(fn,t){let timer//这里用return是因为要反复调用该函数 return function(){if(timer) clearTimeout(timer)timer=setTimeout(function{fn()},t)}
}box.addEventListener('mousemove',_.debounce(mousemove,500))

2、节流

(1)特点

  • 单位时间内,频繁触发事件,只执行一次
  • 王者荣耀技能冷却,期间无法继续释放技能

(2)语法:_.throttle(fun,时间)

(3)使用场景

高频事件:鼠标移动mousemove、页面尺寸缩放resize、滚动条滚动scroll等等

(4)案例

要求:鼠标再盒子上移动,不管移动多少次,每隔500ms才+1

方法1:使用lodash库实现节流,500ms之后采取+1

<script src="./lodash.min.js"></script>
const box=document.querySelector('.box')
let i=1
function mousemove(){box.innerHTML=i++
}box.addEventListener('mousemove',_.throttle(mousemove,500))

方法2:手写节流函数

//核心:利用setTimeout进行实现
//1、声明定时器变量
//2、每次鼠标移动(事件触发)就判断是否有定时器,如果有就先清除定时器
//3、没有就开启定时器,存入到定时器变量里面
//4、定时器里面写函数调用const box=document.querySelector('.box')let i=1function mousemove(){box.innerHTML=i++
}function(fn,t){let timer//这里用return是因为要反复调用该函数 return function(){if(!timer) {timer = setTimeout(function(){fn()timer=null //在setTimeout函数中不能用clearTimeout(timer),因为定时器在运行},t)}
}box.addEventListener('mousemove',_.debounce(mousemove,500))

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

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

相关文章

Linux系统如何使用tcpdump实时监控网络速度:方法与技巧解析

在网络管理和故障排查中&#xff0c;了解网络速度是一个重要的环节。而tcpdump&#xff0c;作为一个强大的网络数据包分析工具&#xff0c;不仅可以用于分析数据包的内容&#xff0c;还能用于实时监控网络速度。本文将介绍Linux系统如何使用tcpdump来实时监控网络速度。 首先&…

什么是 Transformer 机器学习模型?

此为视频What are Transformers (Machine Learning Model)?的笔记。 其实标题里已经揭示了最重要的一点&#xff1a;Transformer&#xff0c;也就是GPT中的T&#xff0c;是一种机器学习模型&#xff0c;或者更准确的说&#xff0c;是一种深度学习模型。基于翻译为中文可能会导…

jmeter的函数助手使用方法

如某个上传文件接口&#xff0c;一个文件只能同时被一个接口调用&#xff0c;如果被并发同时调用就会报错 创建多个测试文件 比如50并发&#xff0c;创建更多的文件防止并发多时随机数生成重复 生成随机数函数 工具–函数助手-选择random-输入范围&#xff08;1-696&#…

基于net的医院病历管理系统

摘 要 伴随着我国社会的发展&#xff0c;人民生活质量日益提高。互联网逐步进入千家万户&#xff0c;改变传统的管理方式&#xff0c;医院病历管理系统以互联网为基础&#xff0c;利用net技术&#xff0c;和SQL Server数据库开发设计一套医院病历管理系统&#xff0c;提高工作…

【鸿蒙HarmonyOS开发笔记】通知模块之发布基础类型通知,内含如何将图片变成PixelMap对象

通知简介 应用可以通过通知接口发送通知消息&#xff0c;终端用户可以通过通知栏查看通知内容&#xff0c;也可以点击通知来打开应用。 通知常见的使用场景&#xff1a; 显示接收到的短消息、即时消息等。 显示应用的推送消息&#xff0c;如广告、版本更新等。 显示当前正…

基于SpringBoot的学生成绩管理系统

基于SpringBootVue的家教管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 系统功能结构展示 登录界面图 现今&#xff0c;越来越多的人乐于选择一项合适的管理方案&#xff0c;但是普通用户往往受到管理经验地限制&…

利用 STM32 TIMER 触发 ADC 实现分组转换

1、问题描述 使用 STM32G4 系列芯片开发产品&#xff0c;用到其中一个 ADC 模块的多个通道&#xff0c;他希望使 用 TIMER 来定时触发这几个通道的转换。不过他有两点疑惑。第一&#xff0c;他期望定时器触发这几个 通道是每触发一次则只转换一个通道&#xff0c;这样依次触发…

五、分支结构

一、程序的组织结构 无论程序是大是小&#xff0c;都可以用顺序结构、选择结构和循环结构表示 二、单分支结构 单分支结构&#xff1a;如果表达式的值是True就执行代码&#xff0c;如果表达式的值是False就跳过语句执行后面语句 ageint(input(请输入你的年龄&#xff1a;)) i…

聚类分析 | Matlab实现基于PCA+DBO+K-means的数据聚类可视化

聚类分析 | Matlab实现基于PCADBOK-means的数据聚类可视化 目录 聚类分析 | Matlab实现基于PCADBOK-means的数据聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 PCA&#xff08;主成分分析&#xff09;、DBO&#xff08;蜣螂优化算法&#xff09;和K-means聚类…

ASP.NET 服务器控件

目录 一、使用的软件 1、下载 2、新建文件&#xff08;写一个简单的web网页&#xff09; 二、相关知识点 1、Web窗体网页的组件 &#xff08;1&#xff09;可视化组件 &#xff08;2&#xff09;用户接口逻辑 2、Web Form网页的代码模型 &#xff08;1&#xff09;单文件…

在基于全志V851se的TinyVision上手动构建 Linux 6.1 + Debian 12 镜像

构建 SyterKit 作为 Bootloader SyterKit 是一个纯裸机框架&#xff0c;用于 TinyVision 或者其他 v851se/v851s/v851s3/v853 等芯片的开发板&#xff0c;SyterKit 使用 CMake 作为构建系统构建&#xff0c;支持多种应用与多种外设驱动。同时 SyterKit 也具有启动引导的功能&a…

C# 数组(Array)

C# 数组&#xff08;Array&#xff09; 初始化数组 声明一个数组不会在内存中初始化数组。当初始化数组变量时&#xff0c;您可以赋值给数组。 数组是一个引用类型&#xff0c;所以您需要使用 new 关键字来创建数组的实例。 例如&#xff1a; double[] b new double[10];…

宝宝洗衣机十大排名:2024年十大超高销量婴儿洗衣机整理

婴儿的衣物对于卫生要求需要高一些&#xff0c;其抵抗力是比较弱的&#xff0c;再加上普通洗衣机无法对婴儿的衣物进行有效的消毒处理&#xff0c;轻则会对婴儿的健康造成威胁&#xff0c;重则会导致皮肤病的发生。因此&#xff0c;一台可以对衣物进行高温除菌的婴儿洗衣机非常…

【Flutter】文件选择器(file_picker)的用法

Flutter 没有提供内置的文件选择器&#xff0c;但社区内有人贡献了一个比较完整的解决方案——file_picker。 file_picker 的 API 简洁易用&#xff0c;支持全平台&#xff08;Android / iOS / Mac / Linux / Windows&#xff09;&#xff0c;是我开发桌面应用时的首选。 这边…

蓝桥杯刷题-替换字符

代码&#xff1a; 顺着题目意思写即可 sinput() nint(input()) for i in range(n):l, r, x, y input().split() if x not in s[int(l)-1:int(r)]: # 如果待替换字符不在区间内则跳过continueelse:# 找到待替换字符的位置&#xff0c;用replace函数进行替换ss[:int(l)-1]s[in…

【C++】CC++内存管理

目录 一、C/C内存分布二 、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三、 C内存管理方式3.1 new/delete操作内置类型3.2 new和delete操作自定义类型3.3 长度域 四、operator new与operator delete函数五、new和delete的实现原理5.1 内置类型5.2 自定义类…

第十二届蓝桥杯省赛CC++ 研究生组-货物摆放

还是整数分解问题,注意n本身也是约数 #include <iostream> int main(){printf("2430");return 0; }#include <iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; const ll n 2021041820210418LL…

更安全的C gets()和str* 以及fgets和strcspn的用法

#include <stdio.h>int main() {char *str;gets(str);puts(str);return(0); }可以说全是错误 首先char *str没有指向一个分配好的地址&#xff0c;就直接读入&#xff0c;危险 ps: 怎么理解char *str "Hello World" 是将一个存储在一个只读的数据段中字符串常…

Linux查看硬件型号详细信息

1.查看CPU &#xff08;1&#xff09;使用cat /proc/cpuinfo或lscpu &#xff08;2&#xff09;使用dmidecode -i processor Dmidecode 这款软件允许你在 Linux 系统下获取有关硬件方面的信息。Dmidecode 遵循 SMBIOS/DMI 标准&#xff0c;其输出的信息包括 BIOS、系统、主板、…

Docker启动失败,报错Is the docker daemon running? Is the docker daemon running?

问题&#xff1a; docker没有正常启动 解决方法&#xff1a; systemctl daemon-reload systemctl restart docker.service