JavaScript 进阶(上)
作用域
局部作用域
局部作用域分为函数作用域和块作用域。
函数作用域:
在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。
总结:
-
函数内部声明的变量,在函数外部无法被访问
-
函数的参数也是函数内部的局部变量
-
不同函数内部声明的变量无法互相访问
-
函数执行完毕后,函数内部的变量实际被清空了
块作用域
在 JavaScript 中使用 { } 包裹的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问。
总结:
-
let 声明的变量会产生块作用域,var 不会产生块作用域
-
const 声明的常量也会产生块作用域
-
不同代码块之间的变量无法互相访问
-
推荐使用 let 或 const
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>for (var i = 1; i <= 3; i++) {// 块作用域console.log(i)}console.log(i);for (let i = 1; i <= 3; i++) {// 块作用域console.log(i)}if (true) {let i = 10}console.log(i)</script>
</body></html>
效果
全局作用域
<script>
标签和 .js
文件的【最外层】就是所谓的全局作用域,在此声明的变量在函数内部也可以被访问。
<script>// 此处是全局function sayHi() {// 此处为局部}// 此处为全局
</script>
全局作用域中声明的变量,任何其它作用域都可以被访问
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 全局变量 nameconst name = '小明'// 函数作用域中访问全局function sayHi() {// 此处为局部console.log('你好' + name)}sayHi();// 全局变量 flag 和 xconst flag = truelet x = 10// 块作用域中访问全局if(flag) {let y = 5console.log(x + y) // x 是全局的}
</script>
</body></html>
效果
总结:
-
为
window
对象动态添加的属性默认也是全局的,不推荐! -
函数中未使用任何关键字声明的变量为全局变量,不推荐!!!
-
尽可能少的声明全局变量,防止全局变量被污染
JavaScript 中的作用域是程序被执行时的底层机制,了解这一机制有助于规范代码书写习惯,避免因作用域导致的语法错误。
作用域链
在解释什么是作用域链前先来看一段代码:
<script>// 全局作用域let a = 1let b = 2// 局部作用域function f() {let c// 局部作用域function g() {let d = 'yo'}}
</script>
函数内部允许创建新的函数,f
函数内部创建的新函数 g
,会产生新的函数作用域,由此可知作用域产生了嵌套的关系。
如下图所示,父子关系的作用域关联在一起形成了链状的结构,作用域链的名字也由此而来。
作用域链本质上是底层的变量查找机制,在函数被执行时,会优先查找当前函数作用域中查找变量,如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域,如下代码所示:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 全局作用域let a = 1let b = 2// 局部作用域function f() {let clet a = 10;console.log(a) //10// console.log(d) // 报错// 局部作用域function g() {let d = 'yo'let b = 20;console.log(b) //20}// 调用 g 函数g()}// console.log(c) // 报错// console.log(d) // 报错f();</script>
</body></html>
效果
总结:
-
嵌套关系的作用域串联起来形成了作用域链
-
相同作用域链中按着从小到大的规则查找变量
-
子作用域能够访问父作用域,父级作用域无法访问子级作用域
JS垃圾回收机制
学习目的: 为了闭包做铺垫
学习路径:
-
什么是垃圾回收机制
-
内存的声明周期
什么是垃圾回收机制
垃圾回收机制(Garbage Collection) 简称 GC
JS中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收。
正因为垃圾回收器的存在,许多人认为JS不用太关心内存管理的问题
但如果不了解JS的内存管理机制,我们同样非常容易成内存泄漏(内存无法被回收)的情况
不再用到的内存,没有及时释放,就叫做内存泄漏
内存的生命周期
JS环境中分配的内存, 一般有如下生命周期:
1 内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存
2 内存使用:即读写内存,也就是使用变量、函数等
3 内存回收:使用完毕,由垃圾回收自动回收不再使用的内存
4 说明:
全局变量一般不会回收(关闭页面回收);
一般情况下局部变量的值, 不用了, 会被自动回收掉
闭包
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解:闭包 = 内层函数 + 外层函数的变量
也就是内层函数用到了外层函数里面的变量
先看个简单的代码:
可以看到这个变量a作用于在局部和全局作用域中间,叫closure,也就是闭包的英文。
但是如果我不引用相对与内层函数的外层变量,那么就不会显示闭包
闭包作用:封闭数据,提供操作,外部也可以访问函数内部的变量
闭包的基本格式
闭包应用:实现数据的私有
比如,我们要做个统计函数调用次数,函数调用一次,就++
变量提升
变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问(仅存在于var声明变量)
注意:
-
变量在未声明即被访问时会报语法错误
-
变量在var声明之前即被访问,变量的值为 undefined
-
let/const 声明的变量不存在变量提升
-
变量提升出现在相同作用域当中
-
实际开发中推荐先声明再访问变量
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 1. 把所有var声明的变量提升到 当前作用域的最前面// 2. 只提升声明, 不提升赋值// var num// console.log(num + '件')// num = 10// console.log(num)function fn() {console.log(num)var num = 10}fn()</script>
</body></html>
函数进阶
知道函数参数默认值、动态参数、剩余参数的使用细节,提升函数应用的灵活度,知道箭头函数的语法及与普通函数的差异。
函数提升
函数提升与变量提升比较类似,是指函数在声明之前即可被调用。
<script>// 调用函数foo()// 声明函数function foo() {console.log('声明之前即被调用...')}
// 不存在提升现象bar() // 错误var bar = function () {console.log('函数表达式不存在提升现象...')}
</script>
效果
总结:
-
函数提升能够使函数的声明调用更灵活
-
函数表达式不存在提升的现象
-
函数提升出现在相同作用域当中
函数参数
函数参数的使用细节,能够提升函数应用的灵活度。
学习路径:
-
动态参数
-
剩余参数
产品需求: 写一个求和函数
不管用户传入几个实参,都要把和求出来
形参我改咋写?
动态参数
arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参
总结:
-
arguments 是一个伪数组,只存在于函数中
-
arguments 的作用是动态获取函数的实参
-
可以通过for循环依次得到传递过来的实参
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>function getSum() {// arguments 动态参数 只存在于 函数里面// 是伪数组 里面存储的是传递过来的实参// console.log(arguments) [2,3,4]let sum = 0for (let i = 0; i < arguments.length; i++) {sum += arguments[i]}console.log(sum)}getSum(2, 3, 4)getSum(1, 2, 3, 4, 2, 2, 3, 4)</script>
</body></html>
效果
剩余参数
剩余参数允许我们将一个不定数量的参数表示为一个数组
那和arguments 有什么不同吗?
剩余参数
-
... 是语法符号,置于最末函数形参之前,用于获取多余的实参
-
借助 ... 获取的剩余实参,是个真数组
开发中,还是提倡多使用 剩余参数。
效果
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>function getSum(a, b, ...arr) {console.log(arr) // 使用的时候不需要写 ...}getSum(2, 3)getSum(1, 2, 3, 4, 5)</script>
</body></html>
效果
展开运算符
展开运算符(…),将一个数组进行展开
说明:
-
不会修改原数组
展开运算符(…),将一个数组进行展开
典型运用场景: 求数组最大值(最小值)、合并数组等
剩余参数:函数参数使用,得到真数组
展开运算符:数组中使用,数组展开
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>const arr1 = [1, 2, 3]// 展开运算符 可以展开数组console.log(...arr1)// console.log(Math.max(1, 2, 3))// ...arr1 === 1,2,3// 1 求数组最大值console.log(Math.max(...arr1)) // 3console.log(Math.min(...arr1)) // 1// 2. 合并数组const arr2 = [3, 4, 5]const arr = [...arr1, ...arr2]console.log(arr)</script>
</body></html>
效果
箭头函数
使用场景:箭头函数更适用于那些本来需要匿名函数的地方
学习路径:
-
基本语法
-
箭头函数参数
-
箭头函数this
基本语法
语法1:基本写法
语法2:只有一个参数可以省略小括号
语法3:如果函数体只有一行代码,可以写到一行上,并且无需写 return 直接返回值
语法4:加括号的函数体返回对象字面量表达式
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// const fn = function () {// console.log(123)// }// 1. 箭头函数 基本语法const fn = () => {console.log(123)}fn()const fn1 = (x) => {console.log(x)}fn1(1)// 2. 只有一个形参的时候,可以省略小括号const fn2 = x => {console.log(x)}fn2(1)// // 3. 只有一行代码的时候,我们可以省略大括号const fn3 = x => console.log(x)fn3(1)// 4. 只有一行代码的时候,可以省略returnconst fn4 = x => x + xconsole.log(fn4(1))// 5. 箭头函数可以直接返回一个对象const fn5 = (uname) => ({ uname: uname })console.log(fn5('刘德华'))</script>
</body></html>
效果
箭头函数参数
-
普通函数有arguments 动态参数
-
箭头函数没有 arguments 动态参数,但是有 剩余参数 ..args
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 1. 利用箭头函数来求和const getSum = (...arr) => {let sum = 0for (let i = 0; i < arr.length; i++) {sum += arr[i]}return sum}const result = getSum(2, 3, 4)console.log(result) // 9</script>
</body></html>
效果
箭头函数 this
在箭头函数出现之前,每一个新函数根据它是被如何调用的来定义这个函数的this值, 非常令人讨厌。
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 以前this的指向: 谁调用的这个函数,this 就指向谁console.log(this) // window// // 普通函数function fn() {console.log(this) // window}window.fn()// 对象方法里面的thisconst obj1 = {name: 'andy',sayHi: function () {console.log(this) // obj}}obj1.sayHi()// 2. 箭头函数的this 是上一层作用域的this 指向const fn = () => {console.log(this) // window}fn()// 对象方法箭头函数 thisconst obj2 = {uname: 'pink老师',sayHi: () => {console.log(this) // this 指向谁? window}}obj2.sayHi()const obj3 = {uname: 'pink老师',sayHi: function () {console.log(this) // objlet i = 10const count = () => {console.log(this) // obj }count()}}obj3.sayHi()</script>
</body></html>
效果
在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window,因此DOM事件回调函数为了简便,还是不太推荐使用箭头函数
解构赋值
以上要么不好记忆,要么书写麻烦,此时可以使用解构赋值的方法让代码更简洁
解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值。
数组解构
数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法。
基本语法:
-
赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
-
变量的顺序对应数组单元值的位置依次进行赋值操作
基本语法:典型应用交互2个变量
数组解构
数组开头的,特别是前面有语句的一定注意加分号
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// const arr = [100, 60, 80]// 数组解构 赋值// // const [max, min, avg] = arrconst [max, min, avg] = [100, 60, 80]// // const max = arr[0]// // const min = arr[1]// // const avg = arr[2]console.log(max) // 100console.log(avg) // 80// 交换2个变量的值let a = 1let b = 2;[b, a] = [a, b]console.log(a, b)</script>
</body></html>
实战
变量多 单元值少的情况
变量的数量大于单元值数量时,多余的变量将被赋值为 undefined
变量少 单元值多的情况
依次赋值
利用剩余参数解决变量少 单元值多的情况
剩余参数返回的还是一个数组
防止有undefined传递单元值的情况,可以设置默认值
允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效
按需导入,忽略某些返回值
支持多维数组的结构
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>const pc1 = ['海尔', '联想', '小米', '方正'];[hr, lx, mi, fz] = pcconsole.log(hr, lx, mi, fz);function getValue() {return [100, 60]}[max, min] = getValue()console.log(max, min);const pc = ['海尔', '联想', '小米', '方正']const [hr, lx, mi, fz] = ['海尔', '联想', '小米', '方正']console.log(hr)console.log(lx)console.log(mi)console.log(fz)// 请将最大值和最小值函数返回值解构 max 和min 两个变量function getValue() {return [100, 60]}const [max, min] = getValue()console.log(max)console.log(min)// 1. 变量多, 单元值少 , undefinedconst [a1, b1, c1, d1] = [1, 2, 3]console.log(a1) // 1console.log(b1) // 2console.log(c1) // 3console.log(d1) // undefined// 2. 变量少, 单元值多const [a2, b2] = [1, 2, 3]console.log(a2) // 1console.log(b2) // 2// 3. 剩余参数 变量少, 单元值多const [a3, b3, ...c3] = [1, 2, 3, 4]console.log(a3) // 1console.log(b3) // 2console.log(c3) // [3, 4] 真数组// 4. 防止 undefined 传递const [a4 = 0, b4 = 0] = [1, 2]const [a5 = 0, b5 = 0] = []console.log(a4) // 1console.log(b4) // 2// 5. 按需导入赋值const [a6, b6, , d6] = [1, 2, 3, 4]console.log(a6) // 1console.log(b6) // 2console.log(d6) // 4const arr1 = [1, 2, [3, 4]]console.log(arr1[0]) // 1console.log(arr1[1]) // 2console.log(arr1[2]) // [3,4]console.log(arr1[2][0]) // 3// 多维数组解构const arr = [1, 2, [3, 4]]const [a7, b7, c7] = [1, 2, [3, 4]]console.log(a7) // 1console.log(b7) // 2console.log(c7) // [3,4]const [a8, b8, [c8, d8]] = [1, 2, [3, 4]]console.log(a8) // 1console.log(b8) // 2console.log(c8) // 3console.log(d8) // 4</script></body></html>
对象解构
对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法
基本语法:
1 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
2 对象属性的值将被赋值给与属性名相同的变量
3 注意解构的变量名不要和外面的变量名冲突否则报错
4.对象中找不到与变量名一致的属性时变量值为 undefined
给新的变量名赋值
可以从一个对象中提取变量并同时修改新的变量名
冒号表示“什么值:赋值给谁”
数组对象解构
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// 对象解构const obj = {uname1: 'pink老师',age1: 18}obj.unameobj.age // 解构的语法const { uname1, age1 } = {age1: 18, uname1: 'pink老师' }// 等价于 const uname1 = obj.uname// 要求属性名和变量名必须一直才可以console.log(uname1)console.log(age1)// 1. 对象解构的变量名 可以重新改名 旧变量名: 新变量名const { uname1: username, age2 } = { uname1: 'pink老师', age2: 18 }console.log(username)console.log(age2)// 2. 解构数组对象const pig = [{uname: '佩奇',age: 6}]const [{ uname, age }] = pigconsole.log(uname)console.log(age)</script>
</body></html>
效果
多级对象解构
实例1
实例2
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// const pig = {// name: '佩奇',// family: {// mother: '猪妈妈',// father: '猪爸爸',// sister: '乔治'// },// age: 6// }// // 多级对象解构// const { name, family: { mother, father, sister } } = pig// console.log(name)// console.log(mother)// console.log(father)// console.log(sister)const person = [{name: '佩奇',family: {mother: '猪妈妈',father: '猪爸爸',sister: '乔治'},age: 6}]const [{ name, family: { mother, father, sister }, age }] = personconsole.log(name)console.log(mother)console.log(father)console.log(sister)console.log(age)</script>
</body></html>
效果
forEach()
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数
主要使用场景: 遍历数组的每个元素
语法:
例如:
注意:
-
forEach 主要是遍历数组
-
参数当前数组元素是必须要写的, 索引号可选。
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><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>
</body></html>
效果
筛选数组 filter 方法(重点)
filter() 筛选数组
返回值:返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组
参数:currentValue 必须写, index 可选
因为返回新数组,所以不会影响原数组
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><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>
</body></html>
效果
深入对象
创建对象三种方式
1. 利用对象字面量创建对象
2. 利用 new Object 创建对象
3. 利用构造函数创建对象
构造函数
构造函数 :是一种特殊的函数,主要用来初始化对象
使用场景:常规的 {...} 语法允许创建一个对象。比如我们创建了佩奇的对象,继续创建乔治的对象还需要重新写一遍,此时可以通过构造函数来快速创建多个类似的对象。
构造函数在技术上是常规函数。
不过有两个约定:
-
它们的命名以大写字母开头。
-
它们只能由 "new" 操作符来执行。
构造函数语法:大写字母开头的函数
创建构造函数:
说明:
-
使用 new 关键字调用函数的行为被称为实例化
-
实例化构造函数时没有参数时可以省略 ()
-
构造函数内部无需写return,返回值即为新创建的对象
-
构造函数内部的 return 返回的值无效,所以不要写return
-
new Object() new Date() 也是实例化构造函数
实例成员:
通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员。
说明:
-
实例对象的属性和方法即为实例成员
-
为构造函数传入参数,动态创建结构相同但值不同的对象
-
构造函数创建的实例对象彼此独立互不影响。
静态成员:
构造函数的属性和方法被称为静态成员
说明:
-
构造函数的属性和方法被称为静态成员
-
一般公共特征的属性或方法静态成员设置为静态成员
-
静态成员方法中的 this 指向构造函数本身
内置构造函数
在 JavaScript 中最主要的数据类型有 6 种:
基本数据类型:
字符串、数值、布尔、undefined、null
引用类型:
对象
但是,我们会发现有些特殊情况:
其实字符串、数值、布尔、等基本类型也都有专门的构造函数,这些我们称为包装类型。
JS中几乎所有的数据都可以基于构成函数创建。
引用类型
Object,Array,RegExp,Date 等
包装类型
String,Number,Boolean 等
Object
Object 是内置的构造函数,用于创建普通对象。
推荐使用字面量方式声明对象,而不是 Object 构造函数
学习三个常用静态方法(静态方法就是只有构造函数Object可以调用的)
作用:Object.keys 静态方法获取对象中所有属性(键)
语法:
注意: 返回的是一个数组
作用:Object.values 静态方法获取对象中所有属性值
语法:
注意: 返回的是一个数组
作用:Object. assign 静态方法常用于对象拷贝
语法:
使用:经常使用的场景给对象添加属性
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>const o = { uname: 'pink', age: 18 }// 1.获得所有的属性名console.log(Object.keys(o)) //返回数组['uname', 'age']// 2. 获得所有的属性值console.log(Object.values(o)) // ['pink', 18]// 3. 对象的拷贝const oo = {}Object.assign(oo, o)console.log(oo)Object.assign(o, { gender: '女' })console.log(o)</script>
</body></html>
结果
Array
Array 是内置的构造函数,用于创建数组
创建数组建议使用字面量创建,不用 Array构造函数创建
数组常见实例方法-核心方法
reduce
数组常见实例方法-核心方法
作用:reduce 返回函数累计处理的结果,经常用于求和等
基本语法:
参数:
起始值可以省略,如果写就作为第一次累计的起始值
累计值参数:
-
如果有起始值,则以起始值算进去
-
如果没有起始值, 则累计值以数组的第一个数组元素作为起始值开始累计
-
后面每次遍历就会用后面的数组元素 累计到 累计值 里面 (类似求和里面的 sum )
累计值:上一次回调函数返回的值。在第一次调用时,累计值的值取决于是否提供了初始值(initialValue)。
当前元素(current value):当前数组元素的值。
使用场景:求和运算:
prev(previous value):上一次回调函数返回的值。在第一次调用时,prev 的值取决于是否提供了初始值(initialValue)。
item(current value):当前数组元素的值。
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// arr.reduce(function(累计值, 当前元素){}, 起始值)// arr.reduce(function (prev, item) {// // console.log(11)// // console.log(prev)// return prev + item// }, 0)// arr.reduce(function (prev, item) {// console.log(11)// // console.log(prev)// return prev + item// })const arr = [1, 2, 3]// const re = arr.reduce((prev, item) => prev + item)const re = arr.reduce(function (prev, item) {console.log(prev)console.log(item)return prev + item})console.log(re)</script>
</body></html>
效果
map
用于对数组中的每个元素执行某种操作,并返回一个新数组,新数组的每个元素是原数组元素经过回调函数处理后的结果。map
方法不会修改原数组,而是返回一个新数组。
基本语法
let newArray = array.map(callback(currentValue[, index[, array]])[, thisArg]);
参数说明
-
callback
:对数组中的每个元素执行的回调函数。-
currentValue
:当前正在处理的元素。 -
index
(可选):当前正在处理的元素的索引。 -
array
(可选):调用map
方法的数组。
-
-
thisArg
(可选):执行回调函数时使用的this
值。 -
返回值:一个新数组,其元素是调用一次回调函数后的返回值。
使用示例
示例 :对数组中的每个元素进行简单的数学运算
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // 输出: [2, 4, 6, 8, 10]
在这个例子中,map
方法将数组 numbers
中的每个元素乘以 2,并返回一个新数组 doubled
。
数组常见方法-其他方法
实例方法 join
数组元素拼接为字符串,返回字符串(重点)
实例方法 find
查找元素, 返回符合测试条件的第一个数组元素值,如果没有符合条件的则返回 undefined(重点)
实例方法every
检测数组所有元素是否都符合指定条件,如果所有元素都通过检测返回 true,否则返回 false(重点)
实例方法some
检测数组中的元素是否满足指定条件 如果数组中有元素满足条件返回 true,否则返回 false
实例方法 concat
合并两个数组,返回生成新数组
实例方法 sort
对原数组单元值排序
实例方法 splice
删除或替换原数组单元
实例方法 reverse
反转数组
实例方法 findIndex
查找元素的索引值
String
String
是内置的构造函数,用于创建字符串。
<script>// 使用构造函数创建字符串let str = new String('hello world!');
// 字面量创建字符串let str2 = '你好,世界!';
// 检测是否属于同一个构造函数console.log(str.constructor === str2.constructor); // trueconsole.log(str instanceof String); // false
</script>
总结:
1 实例属性 length
用来获取字符串的度长(重点)
2 实例方法 split('分隔符')
用来将字符串拆分成数组(重点)
3 实例方法 substring(需要截取的第一个字符的索引[,结束的索引号])
用于字符串截取(重点)
4 实例方法 startsWith(检测字符串[, 检测位置索引号])
检测是否以某字符开头(重点)
5 实例方法 includes(搜索的字符串[, 检测位置索引号])
判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false(重点)
6 实例方法 toUpperCase
用于将字母转换成大写
7 实例方法 toLowerCase
用于将就转换成小写
8 实例方法 indexOf
检测是否包含某字符
9 实例方法 endsWith
检测是否以某字符结尾
10 实例方法 replace
用于替换字符串,支持正则匹配
11 实例方法 match
用于查找字符串,支持正则匹配
注:String 也可以当做普通函数使用,这时它的作用是强制转换成字符串数据类型。
Number
Number
是内置的构造函数,用于创建数值。
<script>// 使用构造函数创建数值let x = new Number('10')let y = new Number(5)
// 字面量创建数值let z = 20
</script>
总结:
-
推荐使用字面量方式声明数值,而不是
Number
构造函数 -
实例方法
toFixed
用于设置保留小数位的长度
实战
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>// toFixed 方法可以让数字指定保留的小数位数const num = 10.923console.log(num.toFixed())console.log(num.toFixed(1))const num1 = 10console.log(num1.toFixed(2))</script>
</body></html>
结果
相关文章:

JavaScript 进阶(上)
作用域 局部作用域 局部作用域分为函数作用域和块作用域。 函数作用域: 在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。 总结: 函数内部声明的变量,在函数外部无法被访问 函数的参数也是函数内部的局部变量 …...

【编译原理实验二】——自动机实验:NFA转DFA并最小化
本篇适用于ZZU的编译原理课程实验二——自动机实验:NFA转DFA并最小化,包含了实验代码和实验报告的内容,读者可根据需要参考完成自己的程序设计。 如果是ZZU的学弟学妹看到这篇,那么恭喜你,你来对地方啦! 如…...

深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据
深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据 一、服务器如何响应前端请求 前端与后端的交互主要通过 HTTP 协议实现。以下是详细步骤: 1. 前端发起 HTTP 请求 GET 请求:用于从服务器获取数据。POST 请求:用…...

如何利用Docker和.NET Core实现环境一致性、简化依赖管理、快速部署与扩展,同时提高资源利用率、确保安全性和生态系统支持
目录 1. 环境一致性 2. 简化依赖管理 3. 快速部署与扩展 4. 提高资源利用率 5. 确保安全性 6. 生态系统支持 总结 使用 Docker 和 .NET Core 结合,可以有效地实现环境一致性、简化依赖管理、快速部署与扩展,同时提高资源利用率、确保安全性和生态…...

@Inject @Qualifier @Named
Inject Qualifier Named 在依赖注入(DI)中,Inject、Qualifier 和 Named 是用于管理对象创建和绑定的关键注解。以下是它们的用途、依赖配置和代码示例的详细说明: 1. 注解的作用 Inject:标记需要注入的构造函数、字段…...

创建 priority_queue - 进阶(内置类型)c++
内置类型就是 C 提供的数据类型,⽐如 int 、 double 、 long long 等。以 int 类型为例,分 别创建⼤根堆和⼩根堆。 这种写法意思是,我要告诉这个优先级队列要建一个什么样的堆,第一个int是要存什么数据类型,vecto…...

2. Java-MarkDown文件解析-工具类
2. Java-MarkDown文件解析-工具类 1. 思路 读取markdown文件的内容,根据markdown的语法进行各个类型语法的解析。引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。 2. 工具类 pom.xml <!-- commonmark 解析markdown --> <d…...

动态规划DP 最长上升子序列模型 登山(题目分析+C++完整代码)
概览检索 动态规划DP 最长上升子序列模型 登山 原题链接 AcWing 1014. 登山 题目描述 五一到了,ACM队组织大家去登山观光,队员们发现山上一共有N个景点,并且决定按照顺序来浏览这些景点,即每次所浏览景点的编号都要大于前一个…...

css-设置元素的溢出行为为可见overflow: visible;
1.前言 overflow 属性用于设置当元素的内容溢出其框时如何处理。 2. overflow overflow 属性的一些常见值: 1 visible:默认值。内容不会被剪裁,会溢出元素的框。 2 hidden:内容会被剪裁,不会显示溢出的部分。 3 sc…...

家居EDI:Hom Furniture EDI需求分析
HOM Furniture 是一家成立于1977年的美国家具零售商,总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品,满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…...

1、开始简单使用rag
文章目录 前言数据存放申请api开始代码安装依赖从文件夹中读取文档文档切块将分割嵌入并存储在向量库中检索部分代码构造用户接口演示提示 整体代码 前言 本章只是简单使用rag的一个示例,为了引出以后的学习,将整个rag的流程串起来 数据存放 一个示例…...

Linux Samba 低版本漏洞(远程控制)复现与剖析
目录 前言 漏洞介绍 漏洞原理 产生条件 漏洞影响 防御措施 复现过程 结语 前言 在网络安全的复杂生态中,系统漏洞的探索与防范始终是保障数字世界安全稳定运行的关键所在。Linux Samba 作为一款在网络共享服务领域应用极为广泛的软件,其低版本中…...

安卓(android)实现注册界面【Android移动开发基础案例教程(第2版)黑马程序员】
一、实验目的(如果代码有错漏,可查看源码) 1.掌握LinearLayout、RelativeLayout、FrameLayout等布局的综合使用。 2.掌握ImageView、TextView、EditText、CheckBox、Button、RadioGroup、RadioButton、ListView、RecyclerView等控件在项目中的…...

【 AI agents】letta:2024年代理堆栈演进(中英文翻译)
The AI agents stack AI 代理堆栈 November 14, 2024 11月 14, 2024原文: The AI agents stack官方教程教程学习笔记: 【memgpt】letta 课程1/2:从头实现一个自我编辑、记忆和多步骤推理的代理Understanding the AI agents landscape 了解 AI 代理环境 Although we see a …...

Java中 instanceof 的用法(详解)
目录 引言 基本语法 基本作用 1. 检查对象是否是指定类的实例 2. 检查对象是否是子类的实例 3. 检查对象是否实现某个接口 4.null 处理 错误分析: 5.综合对比示例 最后总结 注意事项 引言 instanceof 概念在多态中引出,因为在多态发生时&…...

联想拯救者R720笔记本外接显示屏方法,显示屏是2K屏27英寸
晚上23点10分前下单,第二天上午显示屏送到,检查外包装没拆封过。这个屏幕左下方有几个按键,按一按就开屏幕、按一按就关闭屏幕,按一按方便节省时间,也支持阅读等模式。 显示屏是 :AOC 27英寸 2K高清 100Hz…...

【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础
文章目录 1. 前言 本文章基于 RocketMQ 4.9.3 1. 前言 RocketMQ 存储部分系列文章: 【RocketMQ 存储】- RocketMQ存储类 MappedFile 【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础 【RocketMQ 存储】- 一文总结 RocketMQ 的存储结构-基础...

S4 HANA明确税金本币和外币之间转换汇率确定(OBC8)
本文主要介绍在S4 HANA OP中明确明确税金本币和外币之间转换汇率确定(OBC8)相关设置。具体请参照如下内容: 明确税金本币和外币之间转换汇率确定(OBC8) 以上配置,我们可以根据不同公司代码所配置的使用不同的汇率来对税金外币和本币之间进行换算。来针对…...

Cocos Creator 3.8 2D 游戏开发知识点整理
目录 Cocos Creator 3.8 2D 游戏开发知识点整理 1. Cocos Creator 3.8 概述 2. 2D 游戏核心组件 (1) 节点(Node)与组件(Component) (2) 渲染组件 (3) UI 组件 3. 动画系统 (1) 传统帧动画 (2) 动画编辑器 (3) Spine 和 …...

梯度提升用于高效的分类与回归
使用 决策树(Decision Tree) 实现 梯度提升(Gradient Boosting) 主要是模拟 GBDT(Gradient Boosting Decision Trees) 的原理,即: 第一棵树拟合原始数据计算残差(负梯度…...

【单细胞第二节:单细胞示例数据分析-GSE218208】
GSE218208 1.创建Seurat对象 #untar(“GSE218208_RAW.tar”) rm(list ls()) a data.table::fread("GSM6736629_10x-PBMC-1_ds0.1974_CountMatrix.tsv.gz",data.table F) a[1:4,1:4] library(tidyverse) a$alias:gene str_split(a$alias:gene,":",si…...

设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用
文章目录 概述1. 核心思想2. 结构3. 示例代码4. 优点5. 缺点6. 适用场景7. 案例:模板方法模式在数据处理中的应用案例背景UML搭建抽象基类 - 数据处理的 “总指挥”子类定制 - 适配不同供应商供应商 A 的数据处理器供应商 B 的数据处理器 在业务代码中整合运用 8. 总…...

新春登蛇山:告别岁月,启航未来
大年初一,晨曦透过薄雾,温柔地洒在武汉的大街小巷。2025 年的蛇年春节,带着新春的喜气与希望悄然而至。我站在蛇山脚下,心中涌动着复杂的情感,因为今天,我不仅将与家人一起登山揽胜,更将在这一天…...

hive:基本数据类型,关于表和列语法
基本数据类型 Hive 的数据类型分为基本数据类型和复杂数据类型 加粗的是常用数据类型 BOOLEAN出现ture和false外的其他值会变成NULL值 没有number,decimal类似number 如果输入的数据不符合数据类型, 映射时会变成NULL, 但是数据本身并没有被修改 创建表 创建表的本质其实就是在…...

安装最小化的CentOS7后,执行yum命令报错Could not resolve host mirrorlist.centos.org; 未知的错误
文章目录 安装最小化的CentOS7后,执行yum命令报错"Could not resolve host: mirrorlist.centos.org; 未知的错误"错误解决方案: 安装最小化的CentOS7后,执行yum命令报错"Could not resolve host: mirrorlist.centos.org; 未知…...

图论——spfa判负环
负环 图 G G G中存在一个回路,该回路边权之和为负数,称之为负环。 spfa求负环 方法1:统计每个点入队次数, 如果某个点入队n次, 说明存在负环。 证明:一个点入队n次,即被更新了n次。一个点每次被更新时所对应最短路的边数一定是…...

软件工程概论试题三
一、单选 1.需求确认主要检査五个方面的内容,其中那一项是为了保证文档中的需求不互相冲突(即不应该有相互矛盾的约束或者对同一个系统功能有不同的描述)。 A.现实性 B. 可验证性 C.一致性 D.正确性 E.完整性 正答:C 2.下列开发方法中,( )不…...

21.3-启动流程、编码风格(了解) 第21章-FreeRTOS项目实战--基础知识之新建任务、启动流程、编码风格、系统配置 文件组成和编码风格(了解)
21.3-启动流程、编码风格(了解) 启动流程 第一种启动流程(我们就使用这个): 在main函数中将硬件初始化、RTOS系统初始化,同时创建所有任务,再启动RTOS调度器。 第二种启动流程: 在main函数中将硬件初始化、RTOS系统初始化,只…...

未来无线技术的发展方向
未来无线技术的发展趋势呈现出多样化、融合化的特点,涵盖速度、覆盖范围、应用领域、频段利用、安全性等多个方面。这些趋势将深刻改变人们的生活和社会的运行方式。 传输速度提升:Wi-Fi 技术迭代加快,如 Wi-Fi7 理论峰值速率达 46Gbps&#…...

Qt5离线安装包无法下载问题解决办法
想在电脑里装一个Qt,但是直接报错。果然还是有解决办法滴。 qt download from your ip is not allowed Qt5安装包下载办法 方法一:简单直接,直接科学一下,不过违法行为咱不做,遵纪守法好公民(不过没办法阻…...