前端学习笔记 | JS进阶

一、作用域

1、局部作用域

(1)函数作用域

(2)块作用域

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

2、全局作用域

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

3、作用域链

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

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

(1)内存的生命周期

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

(2)算法说明

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

5、闭包

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

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

function outer(){
    let i=1
    return 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=uname
    this.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)//指向window
    console.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)//指向window
    console.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=true
    
    window.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=1

function 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=1

function 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))

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

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

相关文章

AI时代,我靠2个页面,一个AI产品开始变现

大家好&#xff0c;我是AI时间线的作者&#xff0c;AI时间线这个产品是我利用过年期间半天时间开发出来的一个产品。 产品地址:http://www.ai-timeline.top/ 核心功能主要是根据关键词生成时间线&#xff0c;大家可以看看产品上使用教程&#xff0c;非常简单 当然幸运的是目前产…

解决:springboot项目访问hdfs文件提示guava版本不兼容

1、问题描述 版本说明&#xff1a;我用的hadoop版本&#xff1a;3.1.3 项目可以正常启动&#xff0c;但是调用访问hdfs的服务时候报错,报错消息如下&#xff1a;com.google.common.base.preconditions.checkArgument(ZL java/lang/String;Ljava/lang/Object:)V 原因分析&#x…

安科瑞保护测控产品在新能源行业中应用【峰谷套利 动态扩容 需求侧响应】

背景 2 月 10 日发布《关于完善能源绿色低碳转型体制机制和措施的意见》明确&#xff0c;鼓励建设源网荷储一体化、多能互补的智慧能源系统和微电网。 分布式光伏优势 近年来&#xff0c;随着光伏产业规模不断扩大&#xff0c;技术迭代升级不断加快&#xff0c;智能制造迅速推…

如何让工作计划显示在桌面上面?电脑桌面日程安排软件

作为一名忙碌的上班族&#xff0c;我每天都要面对繁多的工作任务&#xff0c;如何确保每一项任务都能按时完成&#xff0c;避免遗漏或忘记&#xff0c;成为了我必须面对的挑战。提前列出工作计划固然有效&#xff0c;但如果能将这些计划直接显示在电脑桌面上&#xff0c;无疑将…

uniapp_微信小程序客服

一、调用api 二、代码 <button open-type"contact">客服</button> 三、小程序后台添加客服人员就行

应急响应靶机训练-Web3题解

前言 接上文&#xff0c;应急响应靶机训练-Web3。 前来挑战&#xff01;应急响应靶机训练-Web3 题解 首先登录用户administrator 寻找隐藏用户 找到隐藏用户hack6618$ 然后去找apache的日志文件 分析得出两个IP地址 192.168.75.129 192.168.75.130 然后更换hack6618$的…

几个好用的AI网站(视频/图片/论文/PPT生成)直接给链接

引入 随着人工智能技术的飞速发展&#xff0c;越来越多的AI创作工具开始涌现&#xff0c;它们不仅能够帮助我们提升写作效率&#xff0c;更能激发创作灵感。今天&#xff0c;就让我们一起来探索十个值得一试的AI网站&#xff0c;它们分别是sora、mused.org、英伟达本地AI、瑞达…

将MySQL数据库在idea中引入

输入SQL语句后运行即可

单片机第四季-第二课:uCos2源码-BSP

1&#xff0c;初始uCos2 文件中uC开头的为uCos相关的。 2&#xff0c;uCos2源码工程建立 建立Source Insight工程 寻找main函数 (1)RTOS其实就是一个大的裸机程序&#xff0c;也是从main开始运行的 (2)main之前也是有一个汇编的启动文件的 (3)main中调用了很多初始化函数 bsp部…

智慧交通运维合集:基于图扑数字孪生技术的解决方案

城市交通作为城市与区域交通体系的核心&#xff0c;其完善程度和发展水平是评价城市现代化水准的关键指标之一。 城市交通数字孪生技术正在成为城市交通管理的关键工具&#xff0c;支持系统的高效运行和安全保障。随着互联网、大数据和人工智能技术的进步&#xff0c;城市交通…

自写系统运行windows程序

运行已经基本正常了。 源代码在 https://gitee.com/enrique11/cxos.git

C++除了Qt还有什么GUI库?

C除了Qt还有什么GUI库&#xff1f; 先&#xff0c;不要折腾&#xff0c;不要想着用 C 来做 App 类的 GUI 开发。 所以你问用 c gui 库&#xff0c;本来确实有很多&#xff0c;但是经过几十年的沉淀&#xff0c;最后只留下一个 qt quick 和其他特殊需求的库&#xff08;包括 qt…

2023年蓝桥杯省赛——平方差

目录 题目链接&#xff1a;1.平方差 - 蓝桥云课 (lanqiao.cn) 思路 暴力偷分 发现规律 发现蹊跷 总结 题目链接&#xff1a;1.平方差 - 蓝桥云课 (lanqiao.cn) 思路 咱就是说&#xff0c;写蓝桥杯的题目的第一件事情是什么&#xff0c;那就是不管三七二十一先暴力一下把能…

图像分类神经网络综述

一、图像分类神经网络发展的四个阶段 经典深度卷积神经网络模型注意力机制卷积神经网络模型轻量级卷积神经网络模型神经网络架构搜索模型 二、深度卷积神经网络模型 1、LeNet 其包含 3 个卷积层 、2 个池化层和 2 个全连接层 , 每个卷积层和全连接层均有可训练的参数, 为深…

Xftp传输文件名乱码问题

背景 项目有个静态文件下载时是几天前的老文件&#xff0c;最新文件不下载。检查路径啥的都没问题后&#xff0c;确定就是当前文件夹。 发现 正当纳闷时候&#xff0c;当前文件中有一个乱码文件&#xff0c;没多想&#xff0c;让同事看一下&#xff0c;他看到老文件名是正常的…

鸿蒙Harmony应用开发—ArkTS-属性动画

组件的某些通用属性变化时&#xff0c;可以通过属性动画实现渐变过渡效果&#xff0c;提升用户体验。支持的属性包括width、height、backgroundColor、opacity、scale、rotate、translate等。布局类改变宽高的动画&#xff0c;内容都是直接到终点状态&#xff0c;例如文字、can…

2024Python计算机二级7

带符号的定点数之中&#xff0c;正数的原码、补码和反码均相同&#xff0c;负数的反码是对该数的原码除符号位外各位取反&#xff0c;补码是在该数的反码的最后&#xff08;即最右边&#xff09;一位上加1&#xff1b;不管是正数还是负数&#xff0c;其补码的符号位取反即是偏移…

Linux常用命令之文件权限类

1.1 Linux的文件属性 在Linux里使用ll或者ls-l命令来显示一个文件的属性以及文件所属的用户和组。 以-开头&#xff1a;普通文件 以d开头&#xff1a;目录 以l开头&#xff1a;链接 以c开头&#xff1a;字符类型的设备文件(例如&#xff1a;鼠标、键盘&#xff0c;他们输入…

网站HTTPS证书怎么获取?有免费的吗?

嘿&#xff0c;朋友们&#xff01;想让你的网站更加安全可靠&#xff0c;让访客安心浏览吗&#xff1f;那就离不开SSL证书的帮助了。SSL证书就像是你网站的守护盾&#xff0c;它能够加密网站与用户浏览器间的通信&#xff0c;使得数据传输过程中既安全又私密。今天&#xff0c;…

【MySQL】存储过程、存储函数、触发器

目录 存储过程介绍技术背景存储过程的作用与优势存储过程跟自定义函数很像。它们的区别是&#xff1a; 存储过程的缺点存储过程的特性基本存储过程使用1.创建语法语法说明&#xff1a;使用案例1.创建获取新闻类别数量的存储过程2.创建获取指定新闻类别ID下新闻数量的存储过程 2…