当前位置: 首页 > news >正文

javascript<——>进阶

一、作用域:变量可以被访问的范围

1.局部作用域

1.1函数作用域

在函数内部声明的变量,在函数内部被访问的,外部无法直接访问。

总结:1、函数内部声明的变量,在函数外部无法直接访问

2、函数的参数也是函数内部的局部变量

3、不同函数内部声明的变量无法互相访问

4、函数执行完毕后,函数内部的变量事件被清空

1.2块作用域

有“{}”的包裹的代码称为代码块,内部声明的变量外部将【有可能】无法被访问

###let /const声明的变量产生块作用域,var声明的不会产生块级作用域

2.全局作用域

写在<script>标签的或者写在js文件的,尽可能少声明全局作用域,防止全局变量被污染

3.作用域链

本质是底层的变量查找机制:(1)函数执行时,优先查找当前函数作用域中查找

                                               (2)查不到则依次逐级查找父级作用域直到全局作用域

###子作用域可以访问父作用域,但是父作用域无法访问子作用域

###相同作用域链按从小到大规则查找变量

4.js垃圾回收机制(GC)

4.1内存生命周期

(1)分配内存:声明变量、函数、对象时,系统自动分配内存

(2)内存使用:读写内存,使用函数,变量

(3)内存回收:使用完毕,垃圾回收机制自动回收不在使用的内存

###全局变量一般不会回收(关闭页面回收),

(4)内存泄漏:程序中分配的内存由于某种原因,程序无法释放或者未释放。

❤️算法说明:

1.栈(操作系统):由操作系统自动分配释放函数的参数值,局部变量等,基本数据类型放到栈里面

2.堆(操作系统):一般由程序员分配释放,不释放,则垃圾回收机制回收。复杂数据类型放到堆里面

4.2垃圾回收算法

(1)引用计数法

跟踪记录被引用的次数,引用一次则记录一次,多次引用会累加++,减少一次引用就--

次数为0,回收

缺点:嵌套使用。两个对象相互引用,尽管它们不再使用,GC不会进行回收,内存泄漏

(2)标记清除法

核心:1.将“不再使用的对象”定义为“无法达到的对象”。

           2.从根部出发定时扫描内存中的对象。凡是从根部到达的对象,都是还需要使用的。

           3.无法触及的对象被标记为不再使用,稍后进行回收。

5.闭包

一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数作用域,会产生内存泄漏

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

<script>
function outer(){let a = 1function fn(){console.log(a)}return fn
}
const fun = outer()
fun()
</script>
//外层函数可以访问内层函数的变量
//const fun = outer() = fn = function fn(){}
//调用fun()

作用:闭包的应用:实现数据的私有,封闭数据。做个统计函数调用次数,调用一次就++

外部可以访问函数内部的变量

问题:内存泄漏

<script>function count(){let i = 0function fn(){i++console.log(`函数被调用了${i}次`)  }return fn
}
const fun = count()</script>

6.变量提升

把var声明的变量提升到 当前作用域的最前面。

只提升声明,不提升赋值

总结:

  1. 变量在未声明即被访问时会报语法错误

  2. 变量在声明之前即被访问,变量的值为 undefined

  3. let 声明的变量不存在变量提升,推荐使用 let

  4. 变量提升出现在相同作用域当中

  5. 实际开发中推荐先声明再访问变量

<script>
function(){console.log(num)var num = 10
}
fun()等价于
function(){var numconsole.log(num)num = 10
}
fun()
</script>

二、函数进阶

1.函数提升(只提升声明,不提升调用)

声明之前调用

函数表达式 必须先声明和赋值,后调用,否则报错。

总结:1、函数提升能够使函数的声明调用更灵活

2、函数表达式不存在提升的现象

3、函数提升出现在相同作用域当中

2.函数参数

###默认值

总结:1、声明函数时为形参赋值即为参数的默认值

2、如果参数未自定义默认值时,参数的默认值为undefined

3、调用函数时没有差引入对应实参时,参数的默认值被当做实参传入

2.1动态参数

arguments是一个伪数组 只存在于 函数里面

作用是动态的获取函数的实参

可以通过for循环依次得到传递过来的参数

2.2剩余参数

(1)...是语法符号,置于最末函数形参之前,用于获取多余的实参

(2)借助...获取的剩余参数,是个真数组

  <script>function getSum(a,b,...arr){console.log(arr);}getSum(2,3,4,5,6,7)getSum(1,2,3,4,5,6,7,8,9)</script>

##使用场景:用于获取多余的实参

##和动态参数的区别是什么?

        动态参数是伪数组;

        剩余参数是真数组

❤️展开运算符【数组中使用】:将数组的数字全展开

      const arr = [1,2,3,4,5]console.log(...arr)console.log(Math.max(...arr));//求最大值console.log(Math.min(...arr));//求最小值

合并数组:

      const arr1 = [1,2,3]const arr2 = [4,5,6]const arr3 = [...arr1,...arr2]console.log(arr3);// [1,2,3,4,5,6]

3.箭头函数

(1)基本语法

const fn=()=>{

}

##只有一个形参时,可以省略小括号

const fn = x=>{


}

##只有一行代码时,可以省略大括号和return

const fn = (x,y) =>x+y

console.log(fn(1,2))

##箭头函数可以直接返回同一个对象

const fn1 = uname=>({uname:name})

console.log('刘德华')

总结:

1、箭头函数属于表达式函数,因此不存在函数提升

2、箭头函数只有一个参数时可以省略圆括号()

3、箭头函数函数体只有一行时代码可以省略花括号{},并自动作为返回值被返回

(2)箭头函数参数

只有剩余参数,没有动态参数arguments

(3)箭头函数this

箭头函数不会创建自己的this,从自己的作用域链的上一层沿用this

三、解构赋值

1.数组解构 :

将数组的单元值快速批量赋值给一系列变量的简介语法

<script>// 以下代码是否会正常执行,如果不会,如何改正const [min, avg, max] = [100,200,300];//必须加分号(function() {console.log(min);})();</script>
<script>const arr = [60,100,80]const [max,min avg] = arr
//将按照顺序赋值给变量console.log(max)
</script>

交换变量

<script>
let a = 1
let b = 2;
const [b,a]=[a,b]
console.log(a,b)
</script>
<script>1. 变量多, 单元值少 , undefinedconst [a, b, c, d] = [1, 2, 3]console.log(a) // 1console.log(b) // 2console.log(c) // 3console.log(d) // undefined2. 变量少, 单元值多const [a, b] = [1, 2, 3]console.log(a) // 1console.log(b) // 23.  剩余参数 变量少, 单元值多const [a, b, ...c] = [1, 2, 3, 4]console.log(a) // 1console.log(b) // 2console.log(c) // [3, 4]  真数组4.  防止 undefined 传递const [a = 0, b = 0] = [1, 2]const [a = 0, b = 0] = []console.log(a) // 1console.log(b) // 25.  按需导入赋值const [a, b, , d] = [1, 2, 3, 4]console.log(a) // 1console.log(b) // 2console.log(d) // 4const arr = [1, 2, [3, 4]]console.log(arr[0])  // 1console.log(arr[1])  // 2console.log(arr[2])  // [3,4]console.log(arr[2][0])  // 3// 多维数组解构const [a, b, [c, d]] = [1, 2, [3, 4]]console.log(a) // 1console.log(b) // 2console.log(c) // 3console.log(d) // 4</script>

2.对象解构

<script>// 对象解构const obj = {uname: 'pink老师',age: 18}obj.unameobj.age //const uname = 'red老师'解构的语法const { uname, age } = {age: 18, uname: 'pink老师' }// 等价于 const uname =  obj.uname//要求属性名和变量名必须一致才可以
</script>

3.多级对象解构

<script>const pig = {name: '佩奇',family: {mother: '猪妈妈',father: '猪爸爸',sister: '乔治'},age: 6}// // 多级对象解构const { name, family: { mother, father, sister } } = pig
</script>

4.多级数组对象解构

 <script>//多级对象数组解构const person = [{name: '佩奇',family: {mother: '猪妈妈',father: '猪爸爸',sister: '乔治'},age: 6}]const [{ name, family: { mother, father, sister } }] = personconsole.log(name)console.log(mother)console.log(father)console.log(sister)</script>

5.多级对象解构案例

 <script>// 1. 这是后台传递过来的数据const msg = {"code": 200,"msg": "获取新闻列表成功","data": [{"id": 1,"title": "5G商用自己,三大运用商收入下降","count": 58},{"id": 2,"title": "国际媒体头条速览","count": 56},{"id": 3,"title": "乌克兰和俄罗斯持续冲突","count": 1669},]} // 需求1: 请将以上msg对象  采用对象解构的方式 只选出  data 方面后面使用渲染页面const {data} = msgconsole.log(data) // 需求2: 上面msg是后台传递过来的数据,我们需要把data选出当做参数传递给 函数function render({data}){console.log(data)}render(msg)// 需求3, 为了防止msg里面的data名字混淆,要求渲染函数里面的数据名改为 myDatafunction render({data:myData}){console.log(myData)}
</script>

###forEach()方法

用于调用数组的每个元素,并将元素传递给回调函数

注意:

1、forEach主要是遍历数组

2、参数当前数组元素使必须要写的,索引号可选。

  <script>// forEach 就是遍历  加强版的for循环  适合于遍历数组对象const arr = ['red', 'green', 'pink']const result = arr.forEach(function (item, index) {console.log(item)  // 数组元素 red  green pinkconsole.log(index) // 索引号})// console.log(result)</script>

###筛选数组filter方法

filter()方法创建的一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素

使用场景:筛选数组符合条件的元素,并返回筛选之后元素的新数组

语法:

  <script>const arr = [10, 20, 30]// const newArr = arr.filter(function (item, index) {//   // console.log(item)//   // console.log(index)//   return item >= 20// })// 返回的符合条件的新数组const newArr = arr.filter(item => item >= 20)console.log(newArr)</script>

###渲染商品案例

 <script>// 2. 初始化数据const goodsList = [{id: '4001172',name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',price: '289.00',picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',},{id: '4001594',name: '日式黑陶功夫茶组双侧把茶具礼盒装',price: '288.00',picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',},{id: '4001009',name: '竹制干泡茶盘正方形沥水茶台品茶盘',price: '109.00',picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',},{id: '4001874',name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',price: '488.00',picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',},{id: '4001649',name: '大师监制龙泉青瓷茶叶罐',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',},{id: '3997185',name: '与众不同的口感汝瓷白酒杯套组1壶4杯',price: '108.00',picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',},{id: '3997403',name: '手工吹制更厚实白酒杯壶套装6壶6杯',price: '99.00',picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',},{id: '3998274',name: '德国百年工艺高端水晶玻璃红酒杯2支装',price: '139.00',picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',},]function render(arr) {let str = ''arr.forEach(item => {const { name, price, picture } = itemstr += `<div class="item"><img src="${picture}" alt=""><p class="name">${name}</p><p class="price">${price}</p></div>`});document.querySelector('.list').innerHTML = str}render(goodsList)document.querySelector('.filter').addEventListener('click', e => {const { tagName, dataset } = e.targetif (tagName == 'A') {//console.log(11);let arr = goodsListif (dataset.index === '1') {arr = goodsList.filter(item => item.price > 0 && item.price < 100)} else if (dataset.index === '2') {arr = goodsList.filter(item => item.price >= 100 && item.price < 300)} else if (dataset.index === '3') {arr = goodsList.filter(item => item.price >= 300)}render(arr)}})</script>

四、构造函数与数据常用函数

1.深入对象

1.1创建对象三种方式

(1)利用对象字面量创建对象

const 0 = {

        name : 'abc'

}

(2)利用new Object创建对象

const 0 = new Object({name:'abc'})

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

1.2构造函数

一种特殊的函数,主要用来初始化对象。

##使用new关键字的调用函数行为被称为实例化

##实例化构造函数时没有参数可以省略

##构造函数内部无需写return,返回值即新创建的对象

##构造函数内部的return返回值无效,所以不要写return

##new Object()new Date()也是实例化构造函数

两个约定:

<1>命名大写字母开头

<2>它们只能由“new”操作符来执行

<script>function Pig(uname,age){this.uname = unamethis.age = age
}const p = new Pig('peiqi',6)const q = new Pig('qiaozhi',3)console.log(p,q)
</script>

❤️实例化执行过程

(1)创建新对象

(2)构造函数this指向新对象

(3)执行函数构造代码,修改this,添加新属性

(4)返回新的对象

1.3实例成员和静态成员

1.3.1实例成员

通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员(实例属性和实例方法)

1.3.2静态成员

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

<script>function Pig(name){this.name = name
}
Pig.eyes = 2//静态属性
Pig.sayHi = function(){//静态方法console.log(this)
}
Pig.sayHi()
console.log(Pig.eyes)//2
</script>

说明:

1.静态成员只能构造函数来访问

2.静态方法中的this指向构造函数

2.内置构造函数

1.Object

.keys(obj):返回所有属性名

.values(obj):获得所有的属性值【返回的是数组】

 const o = { uname: 'pink', age: 18 }// 1.获得所有的属性名console.log(Object.keys(o))  //返回数组['uname', 'age']// 2. 获得所有的属性值console.log(Object.values(o))  //  ['pink', 18]

.assign(new,old):对象拷贝

 // 3. 对象的拷贝const o = { uname: 'pink', age: 18 }// const oo = {}// Object.assign(oo, o)// console.log(oo)//对象中添加属性Object.assign(o, { gender: '女' })console.log(o)

2.Array

方法作用说明
filter过滤数组返回新数组,返回的是筛选满足条件的数组与数组元素
forEach遍历数组不返回数组,经常用于查找遍历数组元素
map迭代数组返回新数组,返回的是处理后的数组元素,想要使用返回的新数组
reduce累计器返回累计处理的结果,经常用于求和等

join

拼接数组元素拼接成字符串,返回字符串
find查找元素返回符合测试条件的第一个数组,如果没有符合条件的则返回undefined
every检测数组所有元素是否都符合指定条件如果都符合,返回true,否则返回false
sort排序对原数组单元值进行排序
from伪数组转换为真数组返回真数组

<script>const arr =  [1,3,5,7,9]const result = arr.reduce((a,b)=>(a+b),10)console.log(result)//35
</script>

(1)reduce(function(prev,curret){return prev+curret},start)

prev:代表初始值

curret:代表累加的值

start:初始值具体数字

###

1.如果没有初始值,则上一次的值以数组的第一个数组元素的值。

2.每一次循环,把返回值给作为 下一次循环的上一次值。

3.如果有初始值,则起始值作为上一次值。

  <script>const arr = [{name: '张三',salary: 10000}, {name: '李四',salary: 10000}, {name: '王五',salary: 20000},]const money = arr.reduce((prev, item) => prev + item.salary * 1.3, 0)console.log(money)</script>

包装类型:

字符串、数值、布尔类型数据是js底层使用Object构造函数“包装”来的,即为包装类型

3.String

.split【‘分隔符’】:把字符串转换成数组(和join相反)

.substring【第一个索引,最后一个索引】截取字符串

.startsWith(检测字符串,【检测位置的索引号】),检测是否以某字符开头

.includes(搜索的字符串,检测的字符串位置索号),判断一的字符串是否包含在另一个字符串中,根据情况返回true或false

.replace(代替字符串)

4.Number

.toFixed:设置保留小数位的长度,四舍五入。

3.综合案例

五、深入面向对象

1.编程思想

(1)面向过程

分析解决问题的步骤,然后用函数一步一步地实现,使用的时候调用

优点:性能高

缺点:没有面向易维护,复用,扩展

(2)面向对象(oop)

优点:易维护、复用、扩展,使系统更加易于维护,更加灵活

缺点:性能低

分解为一个个对象,然后对象之间分工和合作。

###特性:

【1】封装性:封装代码,js面向对象可以通过构造函数实现的封装,同时将变量和函数组合到一起并能通过this实现数据的共享,所不同的是借助构造函数创建出来的实例对象之间互相不影响。

总结:

1、构造函数体现了面向对象的封装特性

2、构造函数实例创建的对象彼此独立,互不影响。

【2】继承性:继承接口

【3】多态性

2.构造函数

存在浪费内存的问题

3.原型对象

构造函数通过原型分配的函数是所有对象所共享的

###js规定,每一个构造函数都有一个prototype属性,指向另一个对象,所以我们也称为原型对象

###这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存

###我们可以把那些不变的方法,直接定义为prototype对象上,这样所有对象的实例就可以共享这些方法

###构造函数和原型对象中的this都指向实例化的对象

原型作用:
(1)共享方法

(2)可以把那些不变的方法,直接定义在prototype对象上

构造函数和原型里面的this指向谁?

指向实例化对象

constructor 属性

在哪里? 每个原型对象里面都有个constructor 属性(constructor 构造函数)

作用:该属性指向该原型对象的构造函数, 简单理解,就是指向我的爸爸,我是有爸爸的孩子

使用场景:

如果有多个对象的方法,我们可以给原型对象采取对象形式赋值.

但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了

此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

对象原型

构造函数创建实例对象和含有原型对象(prototype),实例对象的__proto__指向原型对象,实例对象的__protype__和原型对象的constructor指向构造函数。

对象都会有一个属性 __proto__ 指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype

原型对象的属性和方法,就是因为对象有__proto__ 原型的存在。

注意:

  • __proto__是JS非标准属性

  • [[prototype]]和__proto__意义相同

  • 用来表明当前实例对象指向哪个原型对象prototype

  • __proto__对象原型里面也有一个 constructor属性,指向创建该实例对象的构造函数

原型继承

继承是面向对象编程的另一个特征,通过继承进一步提升代码封装的程度,JavaScript 中大多是借助原型对象实现继承

的特性。

龙生龙、凤生凤、老鼠的儿子会打洞描述的正是继承的含义。

<body><script>// 继续抽取   公共的部分放到原型上// const Person1 = {//   eyes: 2,//   head: 1// }// const Person2 = {//   eyes: 2,//   head: 1// }// 构造函数  new 出来的对象 结构一样,但是对象不一样function Person() {this.eyes = 2this.head = 1}// console.log(new Person)// 女人  构造函数   继承  想要 继承 Personfunction Woman() {}// Woman 通过原型来继承 Person// 父构造函数(父类)   子构造函数(子类)// 子类的原型 =  new 父类  Woman.prototype = new Person()   // {eyes: 2, head: 1} // 指回原来的构造函数Woman.prototype.constructor = Woman// 给女人添加一个方法  生孩子Woman.prototype.baby = function () {console.log('宝贝')}const red = new Woman()console.log(red)// console.log(Woman.prototype)// 男人 构造函数  继承  想要 继承 Personfunction Man() {}// 通过 原型继承 PersonMan.prototype = new Person()Man.prototype.constructor = Manconst pink = new Man()console.log(pink)</script>
</body>

原型链(查找规则)

基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的结构,我们将原型对象的链状结构关系称为原型链

<body><script>// function Objetc() {}console.log(Object.prototype)console.log(Object.prototype.__proto__)function Person() {}const ldh = new Person()// console.log(ldh.__proto__ === Person.prototype)// console.log(Person.prototype.__proto__ === Object.prototype)console.log(ldh instanceof Person)console.log(ldh instanceof Object)console.log(ldh instanceof Array)console.log([1, 2, 3] instanceof Array)console.log(Array instanceof Object)</script>
</body>

① 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。

② 如果没有就查找它的原型(也就是__ proto__指向的 prototype 原型对象)

③ 如果还没有就查找原型对象的原型(Object的原型对象)

④ 依此类推一直找到 Object 为止(null)

⑤ __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线

⑥ 可以使用 instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

六、深浅拷贝

只针对引用数据类型

1.浅拷贝

拷贝的是地址

常见方法:

(1)拷贝对象:Object.assgin()/展开运算符{…obj}拷贝对象

(2)拷贝数组:Array/ptotype.concat()或者{…arr}

2.深拷贝

拷贝的是对象,不是地址

2.1递归实现深拷贝

1.深拷贝实现拷贝出来的新对象不会影响旧对象 ,通过函数递归实现

2.普通拷贝的话直接赋值就可以,遇到数组再次调用这个递归函数

3.如果遇到对象,就调用递归函数解决对象,【先array,后对象】  

<body><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}const o = {}// 拷贝函数function deepCopy(newObj, oldObj) {debuggerfor (let k in oldObj) {// 处理数组的问题  一定先写数组 在写 对象 不能颠倒if (oldObj[k] instanceof Array) {newObj[k] = []//  newObj[k] 接收 []  hobby//  oldObj[k]   ['乒乓球', '足球']deepCopy(newObj[k], oldObj[k])} else if (oldObj[k] instanceof Object) {newObj[k] = {}deepCopy(newObj[k], oldObj[k])}else {//  k  属性名 uname age    oldObj[k]  属性值  18// newObj[k]  === o.uname  给新对象添加属性newObj[k] = oldObj[k]}}}deepCopy(o, obj) // 函数调用  两个参数 o 新对象  obj 旧对象console.log(o)o.age = 20o.hobby[0] = '篮球'o.family.baby = '老pink'console.log(obj)console.log([1, 23] instanceof Object)// 复习// const obj = {//   uname: 'pink',//   age: 18,//   hobby: ['乒乓球', '足球']// }// function deepCopy({ }, oldObj) {//   // k 属性名  oldObj[k] 属性值//   for (let k in oldObj) {//     // 处理数组的问题   k 变量//     newObj[k] = oldObj[k]//     // o.uname = 'pink'//     // newObj.k  = 'pink'//   }// }</script>
</body>

2.2js库lodash里面cloneDeep

<body><!-- 先引用 --><script src="./lodash.min.js"></script><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}const o = _.cloneDeep(obj)console.log(o)o.family.baby = '老pink'console.log(obj)</script>
</body>

2.3JSON序列化

<body><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}// 把对象转换为 JSON 字符串// console.log(JSON.stringify(obj))const o = JSON.parse(JSON.stringify(obj))console.log(o)o.family.baby = '123'console.log(obj)</script>
</body>

七、异常处理

异常处理指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行

throw抛异常

1、throw抛出异常信息后,程序也会终止执行

2、throw后面跟的是错误提示信息

3、Error对象配合throw使用,能够设置更详细的错误信息

<script>function counter(x, y) {if(!x || !y) {// throw '参数不能为空!';throw new Error('参数不能为空!')}return x + y}counter()
</script>

try/catch捕获错误信息

  1. try...catch 用于捕获错误信息

  2. 将预估可能发生错误的代码写在 try 代码段中

  3. 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息

<script>function foo() {try {// 查找 DOM 节点const p = document.querySelector('.p')p.style.color = 'red'} catch (error) {// try 代码段中执行有错误时,会执行 catch 代码段// 查看错误信息console.log(error.message)// 终止代码继续执行return}finally {//不管代码报不报错误,仍然执行该行代码alert('执行')}console.log('如果出现错误,我的语句不会执行')}foo()
</script>

debugger

八、处理this

1.普通函数this指向

谁调用就指向谁

严格模式下指向undefined

2.箭头函数this指向

箭头函数中的 this 与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在 this !箭头函数中访问的 this 不过是箭头函数所在作用域的 this 变量

总结:1.函数内部不存在this,沿用上一级的this

2.不适用:构造函数、原型函数、dom事件函数等

3.适用:需要使用上层的this的地方

4.如果正确的话,它会在很多地方带来方便。

3.改变this指向

(1)call

<script>// 普通函数function sayHi() {console.log(this);}let user = {name: '小明',age: 18}let student = {name: '小红',age: 16}// 调用函数并指定 this 的值sayHi.call(user); // this 值为 usersayHi.call(student); // this 值为 student// 求和函数function counter(x, y) {return x + y;}// 调用 counter 函数,并传入参数let result = counter.call(null, 5, 10);console.log(result);
</script>

总结:

  1. call方法能够在调用函数的同时指定 this 的值

  2. 使用 call 方法调用函数时,第1个参数为 this 指定的值

  3. call 方法的其余参数会依次自动传入函数做为函数的参数

(2)apply

总结:

  1. apply 方法能够在调用函数的同时指定 this 的值

  2. 使用 apply 方法调用函数时,第1个参数为 this 指定的值

  3. apply 方法第2个参数为数组,数组的单元值依次自动传入函数做为函数的参数

call和apply的区别是?

都是调用函数,都能够改变this指向。但它们的参数不一样,apply传递的必须是数组

(3)bind

不会调用函数,但是能改变this的指向

返回值是个函数,但是这个函数里面的this是更改过的obj

主要应用场景:

call调用函数并且可以传递参数

apply经常跟数组有关系,比如借助数学对象实现求最大值和最小值

bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向

九、防抖节流

防抖(debounce):

单位时间内,频繁触发事件,只执行最后一次

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间

使用场景:输入手机号,邮箱验证输入检测

节流(throttle):

单位时间内,频繁出发事件,只执行一次

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数

使用场景:鼠标移动mousemove,页面尺寸缩放resize、滚动条滚动scroll

相关文章:

javascript<——>进阶

一、作用域&#xff1a;变量可以被访问的范围 1.局部作用域 1.1函数作用域 在函数内部声明的变量&#xff0c;在函数内部被访问的&#xff0c;外部无法直接访问。 总结&#xff1a;1、函数内部声明的变量&#xff0c;在函数外部无法直接访问 2、函数的参数也是函数内部的局…...

Java练习8

一.题目 二.源码 package TestRuMen;import java.util.Random; import java.util.Scanner;public class Test11 {public static void main(String[] args){// 调用 createNumber 方法生成一组随机的中奖号码int[] arrcreateNumber();// 调用 userInputNumber 方法获取用户输入…...

C语言按位操作符

在C语言中&#xff0c;按位操作符直接对整数的二进制位&#xff08;bit&#xff09;进行操作&#xff0c;常用于底层编程、硬件控制或性能优化场景。以下是按位操作符的详细说明和用法&#xff1a; 1. 按位操作符列表 操作符名称功能描述示例&按位与对应位均为1时结果为1&…...

Linux(权限管理)

权限概述 基本概念 定义&#xff1a;Linux权限是操作系统对用户和进程访问资源进行精细化管控&#xff0c;通过读&#xff08;r4&#xff09;、写&#xff08;w2&#xff09;、执行&#xff08;x1&#xff09;三种基础权限组合实现。 其中在运维的角度看它们所对应的操作权限…...

Redis入门到实战——基础篇

一、初识Redis 1. 认识NoSQL 2. 认识Redis Redis诞生于2009年&#xff0c;全称Remote Dictionary Server&#xff0c;远程词典服务器&#xff0c;是一个基于内存的键值型NoSQL数据库。 特征&#xff1a; 键值型&#xff08;key-value&#xff09;&#xff0c;value支持多种…...

ctf.show 卷王杯 pwn签到

pwn签到 64位 ret2libc pwn签到 (1) motalymotaly-VMware-Virtual-Platform:~/桌面$ file pwn pwn: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]0953abcf1dd6…...

Dali 1.1.4 | 使用尖端技术将描述转换成独特艺术品、照片和图像,发挥无限创意

Dali是一款先进的AI图像生成器应用程序&#xff0c;能够根据用户的描述生成不同风格的独特图像。无论是迷人的数字艺术、创新的纹身设计还是独一无二的标志&#xff0c;甚至是超写实的照片&#xff0c;Dali都能轻松应对。这款解锁版为用户提供了更多的创作自由度和无限可能&…...

LeetCode 2906 统计最大元素出现至少K次的子数组(滑动窗口)

给出一个示例&#xff1a; 输入&#xff1a;nums [1,3,2,3,3], k 2 输出&#xff1a;6 解释&#xff1a;包含元素 3 至少 2 次的子数组为&#xff1a;[1,3,2,3]、[1,3,2,3,3]、[3,2,3]、[3,2,3,3]、[2,3,3] 和 [3,3] 。该题也是一个比较简单的滑动窗口的题目&#xff0c;但是…...

文献阅读(三)基于干旱强度和恢复时间的生态系统恢复力评估|《Agricultural and Forest Meteorology》

傅伯杰院士团队发表在《Agricultural and Forest Meteorology》上的一篇文章&#xff0c;定义了一个新的恢复力指标&#xff0c;通过指数拟合曲线表征干旱强度和相应恢复时间的关系&#xff0c;用曲线面积量化恢复力&#xff1b;耦合干旱强度和恢复时间来评估生态系统对干旱的恢…...

32、Server.Transfer和Response.Redirect的区别是什么?

Server.Transfer 和 Response.Redirect 是 ASP.NET 中用于页面跳转的两种方法&#xff0c;但它们在实现机制、性能、URL 显示等方面存在显著区别。以下是两者的核心差异&#xff1a; 1. 实现机制 Server.Transfer 服务器端跳转&#xff1a;直接在服务器内部将请求从当前页面…...

iOS—仿tableView自定义闹钟列表

自定义View实现闹钟列表&#xff0c;左滑删除&#xff0c;滑动列表时收起删除按钮。用代理的方法实现ListView的创建&#xff0c;删除以及开关回调&#xff0c;并实现动画效果。 ClockViewCell使用block通知ListView&#xff0c;ListView通过代理通知上层ClockView 1、文件组…...

Spark,集群搭建-Standalone

集群搭建-Standalone 一、解压 在之前的学习中我们有了一个软件包 spark.3.1.2-bin-hadoop3.2.tgz &#xff08;eg我的在 /opt/software目录下&#xff09;把这个软件包解压到 /opt/module 下&#xff08;也可以自己决定解压到哪里&#xff09;。对应的命令是&#xff1a; t…...

【C++11】新的类功能、lambda

&#x1f4dd;前言&#xff1a; 这篇文章我们来讲讲C11——新的类功能、lambda、包装器 &#x1f3ac;个人简介&#xff1a;努力学习ing &#x1f4cb;个人专栏&#xff1a;C学习笔记 &#x1f380;CSDN主页 愚润求学 &#x1f304;其他专栏&#xff1a;C语言入门基础&#xf…...

stm32 g031g8 flash擦除函数被坑

先记录一下在擦除的时候由于调用了这个FLASH_PageErase(FLASH_BANK_1, secpos); 导致擦除不成功&#xff0c;写入失败。 下面的擦除有问题// 使用 FLASH_PageErase 擦除该页while ((FLASH->SR & FLASH_SR_BSY1) ! 0); // 等待空闲FLASH_PageErase(FLASH_BANK_1, secpo…...

SQL实战:04之SQL中的分组问题求解

文章目录 概述题目&#xff1a;分组问题求解题解第一步&#xff1a;求解差值步骤二&#xff1a;窗口分组累加完整SQL 总结 概述 最近刷题时遇到一些比较有意思的题目&#xff0c;乍一遇上时还不知道怎么求解&#xff0c;在灵光一闪时找到了问题的求解答案&#xff0c;感觉还比…...

基于DrissionPage的实习信息爬虫改造与解析

目录 ​编辑 一、DrissionPage技术优势分析 二、代码改造实现 2.1 环境配置 2.2 爬虫类定义 2.3 核心爬取逻辑 一级页面解析优化 二级页面解析优化 2.4 分页控制机制 三、关键技术解析 3.1 智能元素定位 3.2 请求管理优化 3.3 反爬对抗策略 四、改造前后对比测试…...

react-native打包报错:缺少build文件夹

在React Native项目中&#xff0c;如果你遇到了提示“没有build文件夹”的问题&#xff0c;这通常是因为项目的某些部分没有正确初始化或者配置。以下是一些解决步骤。如果缺少build文件&#xff0c;这会导致你使用gradlew assembleRealease失败&#xff0c;进而无法打包APK。下…...

【无需安装额外软件,JavaScript脚本】B站批量取消关注

步骤 注意&#xff1a; 提前选好需要批量取消关注的分组&#xff01;&#xff01;&#xff01;脚本过程中会提示要求输入B站账号的手机号码作为验证&#xff0c;不是封号&#xff0c;只是验证&#xff01;&#xff01;&#xff01; 打开B站关注页面 进入个人关注网页&#xff0…...

【Linux】第十五章 调度未来任务

1.如何调度延迟的用户任务&#xff1f; at 软件包包含 atd守护进程&#xff0c;和一组命令&#xff08;at、atq等&#xff09;。在默认的 RHEL 安装过程中&#xff0c;将自动安装并启用 atd守护进程。root 及普通用户可以使用 at 命令创建计划任务&#xff0c;atd守护进程提供…...

JVM GC垃圾回收算法

垃圾回收算法&#xff08;GC Algorithms&#xff09; JVM 根据对象生命周期特性&#xff08;分代假设&#xff09;采用不同的回收算法&#xff0c;核心算法包括&#xff1a; 标记-清除&#xff08;Mark-Sweep&#xff09; 此算法执行分两阶段。第一阶段从引用根节点开始标记…...

计算机毕业设计--基于深度学习(U-Net与多尺度ViT)的车牌模糊图像修复算法设计与实现(含Github代码+Web端在线体验界面)

基于深度学习的U-Net架构下多尺度Transformer车牌图像去模糊算法设计与实现 如果想对旧照片进行模糊去除&#xff0c;划痕修复、清晰化&#xff0c;请参考这篇CSDN作品&#x1f447; 计算机毕业设计–基于深度学习的图像修复&#xff08;清晰化划痕修复色彩增强&#xff09;算…...

塑料材料工程师简历模板

模板信息 简历范文名称&#xff1a;塑料材料工程师简历模板&#xff0c;所属行业&#xff1a;其他 | 职位&#xff0c;模板编号&#xff1a;DEEBPX 专业的个人简历模板&#xff0c;逻辑清晰&#xff0c;排版简洁美观&#xff0c;让你的个人简历显得更专业&#xff0c;找到好工…...

Nginx核心功能与LNMP部署

目录 一、引言 二、Nginx 简介 2.1 Nginx 的起源与发展 2.2 Nginx 的特点 三、Nginx 核心功能详解 3.1 HTTP 服务器功能 3.1.1 静态资源处理 3.1.2 HTTP 协议支持 3.2 反向代理功能 3.2.1 反向代理的原理 3.2.2 Nginx 反向代理配置 3.3 负载均衡功能 3.3.1 负载均…...

爬虫学习笔记(五)---数据解析之re

数据提取 前面的爬虫笔记学习的都是如何爬取整个页面的内容&#xff0c;服务器渲染中&#xff0c;数据是直接放在源代码html里面的&#xff0c;大多数情况下整个页面的内容真正需要的只是一小部分&#xff0c;那把这一小部分提取出来的过程就叫做数据提取 数据解析方式 re解…...

ESP32- 开发笔记- 软件开发 4 - GPIO 口

1 背景介绍 GPIO&#xff08;General Purpose Input/Output&#xff09; ——通用输入输出口&#xff0c;就是能由软件自由控制输入&#xff08;接收外界信号&#xff09;或输出&#xff08;发出电平信号&#xff09;的引脚。 ESP32 最核心的功能之一&#xff0c;能被用来控制…...

大前端开发——前端知识渐变分层讲解 利用金字塔原理简化前端知识体系

Web开发基础 核心概念 HTML、CSS和JavaScript&#xff1a;Web开发的三大基石&#xff0c;分别负责结构、样式和行为。 代码管理&#xff1a;随着项目规模扩大&#xff0c;需要将代码拆分成小块&#xff0c;便于维护。 作用域污染&#xff1a;早期所有代码共享全局作用域&…...

面向网络安全的开源 大模型-Foundation-Sec-8B

1. Foundation-Sec-8B 整体介绍 Foundation-Sec-8B 是一个专注于网络安全领域的大型语言模型 (LLM),由思科的基础人工智能团队 (Foundation AI) 开发 。它基于 Llama 3.1-8B 架构构建,并通过在一个精心策划和整理的网络安全专业语料库上进行持续预训练而得到增强 。该模型旨在…...

长效住宅IP是什么?如何获取长效住宅IP?

在当今的互联网世界里&#xff0c;IP地址作为连接用户与网站之间的桥梁&#xff0c;其重要性不言而喻。对于跨境电商、社交媒体运营以及数据采集等领域的专业人士而言&#xff0c;普通的IP地址已无法满足日益复杂的需求。他们更需要一种稳定、安全且持久的长效住宅IP来完成各类…...

零基础实现把知识库接到聆思CSK6大模型开发板上

前言 大模型作为一个语言模型&#xff0c;实际上没有真正的记忆功能。所谓的对话记忆只是开发者将对话历史向GPT发送消息时将最近的对话历史通过提示工程组发送给ChatGPT。换句话说&#xff0c;如果对话历史超过了大模型的最大上下文&#xff0c;GPT会忘记之前的部分&#xff0…...

docker 部署前、后端分离项目详细步骤(从打包到部署)

在平常的开发工作中&#xff0c;一个项目经历需求、开发、测试、上线等步骤。在开发测试完成后&#xff0c;我们需要部署测试环境、生产环境等&#xff0c;那么我们用 docker 方式应该怎么部署呢&#xff1f;前后端分离的项目又该如何部署呢&#xff1f;那么&#xff0c;今天我…...

【深度学习的灵魂】图片布局生成模型LayoutPrompt(1)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;《深度学习理论直觉三十讲》_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目…...

BG开发者日志429:故事模式的思路

1、故事模式已有的一关试验关中&#xff0c;直接揭示了一些重要真相&#xff0c;白给了。 /原设计思路是玩家可以直接玩故事模式&#xff0c;很快就能通关本模式的所有关卡&#xff0c;知道所有真相。 /原表现方式是步行模拟&#xff0c;到地点看对话。 &#xff08;现在看来…...

Linux批量管理:Ansible自动化运维指南

引言 在服务器规模化的时代&#xff0c;Ansible就像一位"自动化指挥官"&#x1f396;️&#xff0c;让你轻松管理成百上千台Linux主机&#xff01;本文将带你全面掌握Ansible的核心用法&#xff0c;从基础架构到高级Playbook&#xff0c;从主机管理到应用部署。无论…...

【AI提示词】第一性原理

提示说明 擅长运用第一性原理思维进行深度问题分析与创新解决方案构建的专家。 提示词 # Role: 第一性原理思考导师## Profile - language: 中文 - description: 擅长运用第一性原理思维进行深度问题分析与创新解决方案构建的专家 - background: 具备理论物理学与哲学复合背…...

【LeetCode】螺旋矩阵

题目 题目链接 请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素&#xff0c;示例如下&#xff1a; 思路 整体思路为模拟。具体地&#xff0c;可以采用“减而治之”的思想&#xff0c;将整个遍历过程拆分为一次次对每一行和每一列的遍历&#xff0c;每次只考虑一行/…...

给 BBRv2/3 火上浇油的 drain-to-target

最近彻底跟 BBR 杠上了&#xff0c;再读一篇落实性论文 Promises and Potential of BBRv3&#xff0c;结论依然是 BBRv3 并未如声称的那般优化公平性&#xff0c;反而可能更糟糕&#xff0c;不得不说又是任重而道远。 说一个我遇到的&#xff0c;讲理之外顺带吐槽。 BBRv1 在…...

后端id类型为long类型时,返回给前端浏览器四舍五入,导致id精度缺失问题

背景 今天在代码里&#xff0c;掉了别人写的接口&#xff0c;有个id的字段是long类型的&#xff0c;我这边加点参数返回给前端&#xff0c;然后前端根据id修改&#xff0c;结果修改的数据记录有&#xff0c;但是没起作用&#xff0c;后来发现根据他传给我的id在后台数据库查不…...

《云原生》核心内容梳理和分阶段学习计划

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息文章目录 云原生核心内容梳理和分阶段学习计划一、云原生核心技术栈(2025年重点方向)二、分阶段学习计划(6-12个月系统性进阶)**阶段1:基础入…...

跟我学C++中级篇——控制死锁

一、同步和死锁 在前面学习多线程和网络编程时&#xff0c;都对线程中数据的同步和数据结构多线程访问的安全问题进行了分析和说明。其实&#xff0c;多线程编程之所以难&#xff0c;难点之一就在这里&#xff0c;数据同步意味着效率和安全的平衡&#xff0c;而这里的安全有一…...

「Mac畅玩AIGC与多模态08」开发篇04 - 基于 OpenAPI Schema 开发专用 Agent 插件

一、概述 本篇介绍如何在 macOS 环境下,通过编写 OpenAPI Schema,开发自定义的专用插件,让智能体可以调用外部 API,扩展功能至任意在线服务。实践内容基于 Dify 平台,适配 macOS 开发环境。 二、环境准备 1. 确认本地开发环境 macOS 系统Dify 平台已完成部署并可访问本…...

“兴火·燎原”总冠军诞生,云宏信息《金融高算力轻量云平台》登顶

“兴火燎原”创新马拉松公开赛2024年度全国总决赛于4月18日在福州举办&#xff0c;云宏科技股份有限公司&#xff08;以下简称&#xff1a;云宏&#xff09;的《金融高算力轻量云平台》项目脱颖而出&#xff0c;夺得全国总冠军。 作为数字中国创新大赛金融领域的核心赛事&…...

MySQL 索引与事务详解

MySQL 索引与事务详解 一、索引&#xff08;Index&#xff09; 1. 索引的作用与原理 索引是数据库的"目录"&#xff0c;能够大幅提高查询速度&#xff0c;但会增加写入开销。MySQL 使用 BTree 作为主要索引结构。 2. 索引类型 (1) 普通索引 CREATE INDEX idx_n…...

洛谷题解 | CF111C Petya and Spiders

目录 题目描述输入格式输出格式输入输出样例 #1输入 #1输出 #1 输入输出样例 #2输入 #2输出 #2 说明/提示题目简化题目思路AC 代码 题目描述 Little Petya loves training spiders. Petya has a board $ nm $ in size. Each cell of the board initially has a spider sitting…...

【深度对比】Google Play与IOS 马甲包处理差异分析

在移动应用发布与推广过程中&#xff0c;马甲包&#xff08;Cloned App / Alternate Version&#xff09; 曾被广泛用于流量测试、风险隔离、多品牌运营等场景中。随着 Google Play 与 Apple App Store 审核政策不断收紧&#xff0c;开发者们越来越关注两个平台对“马甲包”的态…...

【C++】C++11新特性(二)

目录 完美转发 引用折叠&#xff1a; lambda表达式 完美转发 引用折叠&#xff1a; 引用折叠是 C的类型系统规则&#xff0c;用于处理“引用的引用”&#xff08;如 T& &&#xff09;。 在推导过程中&#xff0c;必须折叠成有效的单一引用类型。直接声明引用的引用…...

高等数学-第七版-下册 选做记录 习题9-4

1. 3. 4. 8....

特殊权限管理

特殊权限的类型 SUID&#xff08;Set User ID&#xff09;&#xff1a;当一个可执行文件设置了 SUID 权限后&#xff0c;在执行该文件时&#xff0c;进程会以文件所有者的身份运行&#xff0c;而不是以执行用户的身份。例如&#xff0c;/usr/bin/passwd文件用于修改用户密码&a…...

最新的30个Android Kotlin面试题

以下是2025年最新的30个Android Kotlin面试题及其核心解析&#xff0c;综合了协程、密封类、高阶函数、扩展函数等高频考点&#xff0c;并附有相关引用来源&#xff1a; 一、协程与并发编程 协程与线程的核心区别是什么&#xff1f; 协程是轻量级线程&#xff0c;通过挂起而非阻…...

牛客周赛 Round 91

赛时成绩如下&#xff1a; A. while 题目描述 小歪找到了一个由五个字符构成的字符串&#xff0c;它一次可以选择任意一个字符&#xff0c;将其修改为另一个字符&#xff0c;他想要知道&#xff0c;将这个字符串修改为 "while" 需要的最少操作次数。 解题思路&#x…...

Kafka 的服务端的物理存储架构是什么?零拷贝,mmap,sendfile、DMA gather又是什么?

Kafka 服务端的物理存储架构 Kafka 的物理存储架构设计旨在支持高吞吐、低延迟的数据处理&#xff0c;其核心特点包括&#xff1a; 1. 分区与日志段 主题&#xff08;Topic&#xff09;与分区&#xff08;Partition&#xff09;&#xff1a; Kafka 将每个主题划分为多个分区&…...