js进阶
JS进阶
第一天
- 作用域
代码作用的范围
- 全局作用域 (window对象下):在函数外部的代码区域,在全局作用域下定义的变量称为全局变量,任意作用域都可以使用
- 局部作用域:在函数内部代码的区域,在局部作用域中定义的变量称之为局部变量,局部变量只能在当前作用域使用
- 块级作用域:必须用let或者const关键字且在{}大括号中使用,形成的块级作用域。在块级作用域下声明的变量只能在块级作用域使用,不能在其他作用域使用。常见if,就算在全局下声明也不会是windows使用直接输出块级变量就行
总结:函数属于一个特殊的块级作用域(函数作用域)
在同一个作用域中变量名是不能重复的
- 作用域链
当程序中出现多个嵌套的作用域,作用域之间形成的链状结构
作用:程序在执行过程中,通过作用域链来查找变量指导变量查找规则(就近原则)
就近原则:先在当前作用域中查找变量,如果有就执行没有就沿着作用域链向上查找,如果都找不到就会报错局部函数只能在局部作用域调用
- const关键字 定义常量
- 不会有常量提升
- 常量必须设置默认值,值不能修改
- 在同一个作用域中命名不能重复,不同作用域没事
- 必须先定义后使用
- 可以形成块级作用域
- var关键字 var 用来定义变量
- var 定义的变量名可以重复(在同一个作用域下,)
- var 可以先使用后定义 (正常有钱消费,var 是消费再给钱)
- var 定义的变量会产生变量提升 let或const不会出现变量提升
- var 定义的变量不会自产生块级作用域
- let 关键字 let 用来定义变量
- let 变量不会有变量提升
- let 变量必须要先定义后调用
- let 变量在同一个作用域中变量名不能重复
- let 形成块级作用域
- 变量提升
程序执行代码过程中,var变量,变量的声明提升到当前作用域的开始位置,不包含变量赋值,实质就是遇到var 会提升变量名
- 函数提升
程序在执行代码的过程中,遇到函数的时候将函数的声明提升到当前作用域的开始位置,不包含函数的调用,如果是匿名函数就会报错,适当赋值再调用避免报错
- 函数
函数包含:函数由函数名、参数、函数体、返回值组成。
- 闭包函数
在函数中,其他函数访问当前函数中的变量,闭包就是连接的桥梁,被访问的变量所在的函数(整体函数)为闭包函数
- 调试
浏览器断点调试 scope、global、local、closure闭包
- 闭包的作用
- 延伸变量使用的生命周期和范围
- 规避污染全局变量
* 函数的参数
函数的形参:可以设置默认值,函数中的形参本质就是一个变量,可以直接默认赋值;在没有设置实参的情况下,就是默认值,否则就是实参的值
方法一:
function fn2(a = 1, b = 2) {
console.log(a, b);
}
方法二:
function fn2(a , b ) {
a=a||0{默认值)
b||0(默认值)
console.log(a, b);
}
-
以上是静态设置形参是形参的个数明确;如果不明确形参个数
-
arguments动态参数
arguments是函数中用来保存动态实参信息的一个伪数组
- 只能在函数内使用
- 获取实参的值就要遍历数组
- 剩余参数 ...参数 以(真)数组的形式保存实参信息【arguments的升级版】
- 语法:...参数
- 使用 function 函数名(形参名,形参名,…){}
- 剩余参数的作用与形参的作用是有一样的,都是保存实参的信息 而且是以数组的形式(这是真正的实例数组可以用数组的方法)
- 函数的剩余参数必须设置到形参的最后
- 函数中可以只设置一个剩余参数(用户传递的所有实参都保存到了剩余参数中)函数的剩余参数有且只有一个(a,b,c,...d)/(...d)
- 扩展之扩展数组
...数组 ---->将数组展开
- 分类
-
匿名函数 没有函数名字具有函数参数和返回值但要用变量接收返回值,并且调用变量function(){}
-
高阶函数 函数的参数是一个函数,整个函数就是高级函数setinterval(function(){},时间间隔)
-
回调函数 定时器中的function(){}
-
自调用函数 ()()自调用函数 是一种将函数声明和调用合并到一起的写法,我们称为自执行函数或立即执行函数自执行函数也可以传递参数 自执行函数也普通函数并无本质的区别,同样具有形参与实参
-
递归函数 函数返回值是自身即实现重复自己调用自己循环效果,但必须要有条件控制,避免死循环和栈溢出 可以加if或者return
-
闭包函数 在函数中有权限访问其他函数作用域中的变量的整体函数
-
箭头函数 ()=>{}箭头函数是一个匿名函数;因为是匿名函数所以调用函数的时候将箭头函数赋值给一个变量;匿名函数可以通过自调用写法执行箭头函数的代码;使用有参数和返回值;不能用arguments但是可以用剩余参数;可以使用this关键字,关于this指向问题:
普通函数的this指向window
箭头函数this指向父容器(父级作用域)
箭头函数定义的时候就决定了他的this指向所以箭头函数的this指向是固定的,所在的对象而不是使用箭头函数时所在的对象但是它所在对象的作用域是可变的特点:
- 若果只有一个形参可以省略小括号
- 如果只有一个一行代码,可以省略大括号
- 箭头函数如果有返回值且只有一行代码,return可以省略不写
第二天
- 解构赋值
es6中用来快速获取数组或者对象中值的一种新方式
- 数组解构赋值
语法:let [变量,……]=数组;
内部通过循环遍历的方式将数组中的每一个值依次赋值给设置的变量
如果数组的值多余数组解构中的变量,变量依然得到数组中对应的值;少于就是undefined
数组解构赋值中,变量可以设置点点点形式以数组形式保存
- 对象解构赋值
语法: let obj={对象中的属性:变量,对象中的属性:变量}=对象;
内部遍历对象将变量的值分别赋值给对应的变量
在对象解构赋值中如果属性不存在得到undefined
变量名可以和属性名相同省略变量名,保留属性名
- 面向过程
在解决问题的时候从过程步骤出发
- 面向对象
编程思想,在解决问题是从对象 的角度出发(对象中有哪些属性和方法)
如何创建对象
- 通过字面量创建
let 自定义对象名=new object()
字面量方式是内置构造函数的语法糖
- 通过内置构造函数
let 自法定对象名=new Object()
对象名.自定义属性/方法名=值
对象名.['自定义属性名/方法名']=值
-
内置构造函数本质就是js本身拥有的一个函数用来创建对象 Object
-
new 字
通过new 关键字调用构造函数(创建对象),只要通过构造函数创建的对象就必须要在构造函数前面加new
Date、Array、FileReader、Regexp
数组本身就是一个构造函数
- 通过工厂方式,参数和返回值
在程序中需要批量创建多个对象 new
将构造函数创建对象封装到一个函数中,这个函数就是工厂,属性和方法都是公用的
如果想要单独设置属性或者方法就给通过点或者[]的形式赋值
function Stu (age,name){
let obj=new Object()
obj.name=age
obj.uname=name
return obj //一定要有返回值,不然会undefined
}
let zs=new Stu(15,'zs')
- 通过自定义构造函数 new调用
function 函数名 (形参,实参){
this.属性名=形参
this.属性名=形参
this.方法名=function (){}
}
//通过自定义构造函数创建对象
let 对象名=new 函数名(实参,实参)
//自定义构造函数是工厂方式的简写
- 适用于程序中需要创建多个对象
- 构造函数与普通函数区别
命名:普通函数以动词且驼峰命名法,构造函数通常以帕斯卡命名(首字母大写名词)
this关键字:构造函数中的this关键字指向构造函数创建的对象 (return this 省略) 作用域
- 构造函数的成员
- 静态成员:在构造函数外部通过构造函数设置写属性或者方法点或者[],只能通过构造函数访问
- 实例成员:在构造函数内部设置的属性或者方法称为实例成员,只能通过构造函数创建的实例对象访问
- 内置对象
- Math、Date、FileReader、Array、Object
- 数组内置对象
属性:length
方法(实例方法):
indexOf('数组中的值',从索引为多少的位置开始找) 从数组的开始向数组的结束查找从左往右, 数组中获取值对应的索引号,返回就是找到当前第一个值对应的索引号-1表示数组中没有该值,
lastIndexOf从属组的结束向开始的位置查找,返回值是当前值对应的索引号,查找不到就会返回-1,不管是indexOf还是lastindexOf索引是不变的,只是查找的方向改变了
遍历数组forEach(function(item,index){})参数是一个回调函数
item表示被便利数组中的每一个值;index表示被便利数组中的每一个值对应的索引没有返回值undefined
filter(function(item,index){})遍历数组的同时筛选数组
有返回值返回一个新数组 return 筛选后的结果 设置返回值
map(function(item,index){}) 映射(在遍历数组并修改数组的值)补零,值的个数不变,有返回值返回数组,和filter不同
(静态方法):
Array.from(对象) 将伪数组转换成真正的数组
伪数组:可以按照数组的方式遍历但是不能使用数组提供的方法
queryselectorall、arguments
第三天
- 原型对象 prototype是构造函数的一个属性
作用:设置公共的方法,防止内存浪费
结论:构造函数中的方法不是一个真正意义的公共方法,每创建一个对象就会在内存中开辟一个新的内存地址
语法: 构造函数.prototype.方法名=function(){}
new在内存堆中创建对象然后函数调用生成对象地址最后赋值给实例对象
公共属性也是存储在内存的堆中,栈中保存的值或者地址(对象)
- 对象原型: proto 是实例对象中的一个属性
作用:指向构造函数的原型对象,让实例对象访问原型对象上的方法
在谷歌中____proto____([prototype])直接解析了【】隐式__proto显示----->浏览器显示模式,不用管
-
constructor 保存当前对象属于哪个构造函数,是原型对象和对象原型____proto____/[[prototype]]的一个属性
-
原型链 多个原型对象或者对象原型嵌套形成一个链状结构,指导方法查找执行规则(就近原则向上查找)
- 就近原则 当对象执行方法时首先在当前实例对象上查找如果没有就会沿着——proto————(构造函数的原型对象)上查找,如果也没有就会继续再沿着————proto————查找(此时的constructor指向的是object)中
第四天
- call方法 调用函数修改this指向 通过构造函数实现继承的时候用call方法
函数名.call([this指向的对象名,实参,实参]) 普通函数this指向window,如果有参数的话就不能省略第一个参数即this指向参数对象
- (组合)继承 节省代码,构造函数的作用就是创建对象
调用父级构造函数修改父级构造函数的this指向,需要给call设置第一个参数中的this让他指向子级 的this实例对象,加上参数,有参数必写this指向参数
第四天
-
构造函数实现方法的继承
-
原型继承
-
类 es6中提出的一个新的概念呢,本质就是一个构造函数的新写法
- 定义类 class 自定义类名 {} 首字母大写
- 通过类new 创 建 let 对象名=new 类名() 这里注意只有创建new 的时候类名加()用来传参数
- 通过类设置属性和方法
- 属性 类中的属性必须要通过constructor设置 加this
class 类名{
constructor(形参,……){
this.属性=形参
this.属性=形参
}
}
- 类添加方法
- 不能加function关键字
- 必须写在constructor外面
类和构造函数一样所以命名要遵守帕斯卡命名法首字母大写,类设置方法时写在constructor外面,默认被添加到prototype身上,所以类的本质就是构造函数,如果写在constructor也行,必须加this.方法名=function(){}不推荐内存 通过类创建的时候方法会默认执行一次
- 验证类的本质
- 构造函数可以创建对象,类也可以
- 构造函数有prototype属性,类也有
- 构造函数创建的对象叫实例对象有____proto____属性,类也有
- 构造函数的对象原型和原型对象都有constructor,类也有
- 构造函数中的this指向实例对象,类也是(其中用到了函数作用域this的转换)
- 类的继承 属性和方法 语法:子类 extends 父类{}
- 注意如果在子类继承父类extends 而且子类有自己的constructor,那么继承的时候程序会报错要加super()
- 当子类有自己的constructor的时候必须在this的前面调用super(参数,参数)函数
- super()调用父级constructor构造函数并且修改类中的this的指向
- 子类继承父类时,子类可以设置与父类相同的方法名
- 子类中如果有与父类中同名的方法,则执行的时候执行子类中的方法就算执行多次 (就近原则)原型链
- 如果子类在继承中希望执行父类中同名的方法,通过super.父类方法名()执行
注意:
-
在类中,如果方法中要访问对象的属性,则必须在该属性前加this,指向类实例对象
-
在类中,如果方法和方法之间相互访问,必须在前面加this关键字
-
call,bind,apply区别
- call可以调用函数,修改函数的this指向,call调用带有参数的函数直接添加实参函数.call(对象,实参...)
- apply可以调用函数,修改函数的this的指向,调用带有参数的函数是数组格式函数.apply(对象,[值,值]);
- bind可以调用函数但是不会执行函数 + 修改this指向bind语法: 函数.bind(对象,参数1,参数2...)返回当前函数调用带有参数的函数直接添加实参函数.call(对象,实参...)
本地数据存储
- 简单类型:在栈区中开辟空间,空间名字为变量名字,栈区保存值,栈放的就是一个简单类型的值,函数的形参也是一个变量在栈空间开辟
特殊的字符串特性:不可改变的特性 (不是值不变而是变量在内存中的位置没有改变)所以就是因为不可改变,值并没有删除所以不推荐使用拼接字符串
- 复杂类型:先通过new Object(),在堆中开辟空间,产生一个唯一的内存的地址,将堆区中内存的值拷贝赋值给栈区中的变量,开辟了两块空间
- 将数据保存到本地客户端一般是浏览器
本地存储位置 localstorage sessionstorage
localstorage 对象存储的数据没有时间限制。
- 保存数据 loacalStorage.setItem('键','值') / localStorage.setItem('自定义键',obj),多个对象的话就可以赋值一个数组,把数组保存到本地存储中,记得转换类型,因为对象多这里直接用数组进行转化,成JSON格式的字符串,如果要获取json字符串的值,还需要把数组在转换成对象格式JSON.parse()再通过foreach()遍历数组之后点的格式获取
- 不能直接将对象保存带本地存储中结果是[object,object],需要将
- -对象转换成JSON格式字符串,JSON.stringify(对象) 取值还要分割截取字符串
- 将的到的JSON结果转换成对象方便取值等操作 JSON.parse(结果)用点或者[]操作
- 获取数据 loacalStorage.getItem('键'),如果没有对应的键就会显示null
- 删除数据 localStorage.removeItem('键')
sessionStorage 方法针对一个 session 进行数据存储。当用户关闭浏览器窗口后,数据会被删除。
sessionStorage.setItem('键','值') 设置本地session存储
sessionstorage和localstorage区别
localstorage保存的数据属于持久化保存(除非手动删除);可以跨页面访问;保存的数据大于sessionstorage保存的数据;20m
sessionstorage保存的数据属于临时保存(页面关闭,数据消失);只能在当前页面访问;4m
本文来自博客园,作者:jialiangzai,转载请注明原文链接:https://www.cnblogs.com/zsnhweb/articles/16203983.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异