- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
数组也是一种复合数据类型,在数组可以存储多个不同类型的数据 。
- 数组中存储的是有序的数据,数组中的每个数据都有一个唯一的索引可以通过索引来操作获取数据
- 数组中存储的数据叫做元素
- 任何类型的值都可以成为数组中的元素
// 通过Array创建数组
const arr = new Array()
// 通过[]创建数组
const arr = []
// 通过索引添加元素
arr[0] = "test"
// 如果索引不是连续的,中间的索引也会创建,只是元素是空,应该避免使用非连续数组,性能不好
arr[3] = "2"
// 定义的时候添加元素
const a = new Array(1,3,4)
const arr = ["1","test"]
// 通过索引读取,如果读取一个不存在的元素,返回undefined
const arr = ["1","test"]
arr[0] // "1"
// 获取的实际值是数组的最大的索引+1,非连续数组因为有空值,不会特别准确
console.log(arr.length)
// 向数组的最后添加元素
arr[arr.length] = "3"
// 修改长度,如果改大了,多出的部分会是空元素,如果改小,会从后往前删除元素
arr.length = 10
arr = [1,2,3,4,5,6,7,8,9,10]
// 通过长度遍历-正序
for(let i=0; i < arr.length;++){
console.log(arr[i])
}
// 通过长度遍历-倒序
for(let i=arr.length-1;i>=0;i--){
console.log(arr[i])
}
// for-of语句可以用来遍历可迭代对象
for(let a of arr){
console.log(a)
}
方法大全 。
// 检查一个对象是否是数组
let arr = []
console.log(Array.isArray(arr)) // true
let arr = [1,2,3]
// 根据索引获取数组中的指定元素,
console.log(arr.at(2))
let arr = [1,2,3]
let arr1 = [4,5,6]
// 用来连接两个或多个数组
// 非破坏性方法,不会影响原数组,而是返回一个新的数组
let new_arr = arr.concat(arr1,[7,8])
console.log(new_arr) // [1,2,3,4,5,6,7,8]
let arr = [1,2,3,2]
// 获取元素在数组中第一次出现的索引
// 参数:要查询的元素,查询的起始位置
console.log(arr.indexOf(2)) // 1
console.log(arr.indexOf(2,2)) // 3
let arr = [1,2,3,2]
// 获取元素在数组中最后一次出现的位置,找到了则返回元素的索引,没有找到返回-1
console.log(arr.lastIndexOf(2)) // 3
let arr = [1,2,3,2]
// 将一个数组中的元素连接为一个字符串
console.log(arr.join("~")) // 1~2~3~2
let arr = [1,2,3,2]
// 用来截取数组(非破坏性方法)
/*
参数:1.截取开始的索引(包括该索引元素)
2.截取的结束索引(不包括该索引元素,该参数可以省略不写,如果省略则会一直截取到最后
如果将两个参数全都省略,则可以对数组进行浅拷贝
*/
console.log(arr.slice(0,2)) // [1,2]
// arr1和arr不是复制,两个指向的是一个内存地址,修改任意一个会影响其他数组
let arr = [1,2,3,2]
let arr1 = arr
/*
浅拷贝
通常对对象的拷贝都是浅拷贝
浅拷贝对对象的浅层进行复制(只复制一层)
如果对象中存储的数据是原始值,那么拷贝的深浅是不重要
浅拷贝只会对对象本身进行复制,不会复制对象中的属性(或元素)
调用slice时,会产生一个新的数组对象,从而完成对数组的复制- 浅拷贝
*/
let arr2 = [{"name":"l"},{"name":"q"}]
let arr3 = arr.slice()
/*
深拷贝
深拷贝指不仅复制对象本身,还复制对象中的属性和元素
因为性能问题,通常情况不太使用深拷贝
*/
let arr4 = [{"name":"l"},{"name":"q"}]
let arr5 = structuredClone(arr4)
let arr = [{"name":1},{"name":2}]
// 可以将一个数组中的元素展开到另一个数组中或者作为函数的参数传递,
// 浅复制
let arr2 = [...arr]
console.log(arr2) // [ { name: 1 }, { name: 2 } ]
/*
Object.assign(目标对象, 被复制的对象)
将被复制对象中的属性复制到目标对象里,并将目标对象返回
*/
const obj = {"name":1}
const obj1 = Object.assign({},obj)
console.log(obj1) // { name: 1 }
const obj = {"name":1}
const obj1 = Object.assign({"age":1},obj)
console.log(obj1) // { age: 1, name: 1 }
// 也可以使用展开运算符进行对象复制
const obj = {"name":1}
const obj1 = {...obj}
console.log(obj1) // { name: 1 },将obj中的属性在新对象中展开
const arr = []
// 向数组的末尾添加一个或多个元素,并返回新的长度
let l = arr.push(1,2,3)
console.log(l) // 3
console.log(arr) // [ 1, 2, 3 ]
const arr = [1,2,3,4,5]
// 删除并返回数组的最后一个元素
let a = arr.pop()
console.log(a) // 5
console.log(arr) // [ 1, 2, 3, 4 ]
console.log(arr.length) // 4
const arr = [1,2,3,4,5]
// 向数组的开头添加一个或多个元素,并返回新的长度
let a = arr.unshift(99,98)
console.log(a) // 7
console.log(arr) // [99, 98, 1, 2, 3, 4 ]
const arr = [1,2,3,4,5]
// 删除并返回数组的第一个元素
let a = arr.shift()
console.log(a) // 1
console.log(arr) // [ 2, 3, 4, 5]
console.log(arr.length) // 4
// 可以删除、插入、替换数组中的元素
// 参数:1. 删除的起始位置 2. 删除的数量 3. 要插入的元素 返回值:删除的元素
// 删除元素
const arr = [1,2,3,4,5]
let a = arr.splice(1,2)
console.log(a) // [2,3]
console.log(arr) // [1,4,5]
// 替换元素
const arr = [1,2,3,4,5]
let a = arr.splice(1,1,"ao") // 可以写多个元素
console.log(a) // [2]
console.log(arr) // [ 1, 'ao', 3, 4, 5 ]
// 插入元素
const arr = [1,2,3,4,5]
let a = arr.splice(1,0,"ao","to") //在下表为1的地方开始插入ao,to,后续元素后移
console.log(a) // []
console.log(arr) // [ 1, 'ao','to', 2, 3, 4, 5 ]
// 反转数组
const arr = [1,2,"a","s",5]
arr.reverse()
console.log(arr) // [ 5, 's', 'a', 2, 1 ]
const arr = [1, 2, 3, 2, 4, 1];
// 使用set方法去重
const arr1 = [...new Set(arr)];
console.log(arr1); // [1, 2, 3, 4]
// 循环判断去重
const arr = [1, 2, 1, 3, 2, 2, 4, 5, 5, 6, 7]
const newArr = []
for(let ele of arr){
if(newArr.indexOf(ele) === -1){
newArr.push(ele)
}
}
console.log(newArr)
如果一个函数的参数或返回值是函数,则这个函数就称为高阶函数 将函数作为参数,意味着可以对另一个函数动态的传递代码 。
function user(fn,age){
fn(age)
}
function admin(age){
return age === 18;
}
// 一个函数当做参数传递给另一个函数,这个函数称作回调函数(callback)
user(admin,18)
// 通常回调函数使用匿名函数定义
user(a => age === 18,18)
可以通过高阶函数,来动态的生成一个新函数 。
function a(){
return "hello"
}
function b(fn){
return () => {
// ... 其他自定义代码
return fn()
}
}
可以利用函数,来隐藏不希望被外部访问到的变量 。
闭包: 闭包就是能访问到外部函数作用域中变量的函数 。
什么时候使用: 当我们需要隐藏一些不希望被别人访问的内容时就可以使用闭包 。
构成闭包的条件:
1. 函数的嵌套
内部函数要引用外部函数中的变量 。
内部函数要作为返回值返回 。
function Sum() {
let num = 0 // 位于Sum作用域中
return () => {
num++
return num
}
}
const newFn = new Sum()
console.log(newFn()) // 1
console.log(newFn()) // 2
console.log(newFn()) // 3
函数的作用域在函数创建时就已经确定(词法作用域),和调用位置无关 。
// 闭包的原理就是利用词法作用域
let a = "全局"
function one(){
console.log(a) // 全局
return a
}
function two(){
let a = "局部"
console.log(a) // 局部
one() // 全局
function three(){
console.log(a) // 局部,函数定义是外部变量a是two中的a
}
return three
}
let fn = two()
fn()
闭包的生命周期:
注意事项:
相较于类来说,闭包比较浪费内存空间(类可以使用原型而闭包不能) 。
调用自身的函数称为递归函数 。
递归的作用和循环是基本 一致的 。
function test(num){
// 终止条件
if (num === 1){
return 1
}
// 调用自身
return test(num-1) * num
}
递归的核心思想就是将一个大的问题拆分为一个一个小的问题,小的问题解决了,大的问题也就解决了 。
编写递归函数,一定要包含两个要件:
递归的作用和循环是一致的,不同点在于,递归思路的比较清晰简洁,循环的执行性能比较好 在开发中,一般的问题都可以通过循环解决,也是尽量去使用循环,少用递归 只在一些使用循环解决比较麻烦的场景下,才使用递归 。
/*
sort用来对数组进行排序(会对改变原数组)
sort默认会将数组升序排列
注意:sort默认会按照Unicode编码进行排序,所以如果直接通过sort对数字进行排序
可能会得到一个不正确的结果
参数:
- 可以传递一个回调函数作为参数,通过回调函数来指定排序规则
(a, b) => a - b 升序排列
(a, b) => b - a 降序排列
*/
let arr = [3,3,4,6,8,1,2,10]
arr.sort((a,b) => a -b)
console.log(arr)
/*
用来遍历数组
需要一个回调函数作为参数,这个回调函数会被调用多次
数组中有几个元素,回调函数就会调用几次
每次调用,都会将数组中的数据作为参数传递
回调函数中有三个参数:
element 当前的元素
index 当前元素的索引
array 被遍历的数组
*/
let arr = [3,3,4,6,8,1,2,10]
arr.forEach((element,index,array)=>{
console.log(element)
console.log(index)
console.log(array)
})
/*
将数组中符合条件的元素保存到一个新数组中返回
需要一个回调函数作为参数,会为每一个元素去调用回调函数,并根据返回值(true、false)来决定是否将元素添加到新数组中
非破坏性方法,不会影响原数组
*/
/*
根据当前数组生成一个新数组
需要一个回调函数作为参数,
回调函数的返回值会成为新数组中的元素
非破坏性方法不会影响原数组
*/
let a = ["商城","账户","登录","注册"]
let b = a.map(ele => "<li>" + ele + "</li>")
console.log(b) // [ '<li>商城</li>', '<li>账户</li>', '<li>登录</li>', '<li>注册</li>' ]
/*
可以用来将一个数组中的所有元素整合为一个值
参数:
1. 回调函数,通过回调函数来指定合并的规则
2. 可选参数,初始值
*/
let arr = [1,2,3,4,5,6,7,8,10]
let b = arr.reduce((a,b) => a+b)
console.log(b) // 46
let arr2 = [1,2,3,4,5,6,7,8,10]
let b2 = arr2.reduce((a,b) => a+b,10)
console.log(b2) // 56
/*
arguments是函数中又一个隐含参数
arguments是一个类数组对象(伪数组)
和数组相似,可以通过索引来读取元素,也可以通过for循环变量,但是它不是一个数组对象,不能调用数组的方法
arguments用来存储函数的实参,
无论用户是否定义形参,实参都会存储到arguments对象中
可以通过该对象直接访问实参
*/
function test(){
console.log(arguments) // { '0': 1, '1': 3, '2': 4 }
console.log(arguments[0]) // 1
}
test(1,3,4)
/*
可变参数,在定义函数时可以将参数指定为可变参数
- 可变参数可以接收任意数量实参,并将他们统一存储到一个数组中返回
- 可变参数的作用和arguments基本是一致,但是也具有一些不同点:
1. 可变参数的名字可以自己指定
2. 可变参数就是一个数组,可以直接使用数组的方法
3. 可变参数可以配合其他参数一起使用,当可变参数和普通参数一起使用时,需要将可变参数写到最后
*/
function test(...args){
console.log(args) // [ 1, 3, 4 ]
console.log(args[0]) // 1]
}
test(1,3,4)
调用函数除了通过函数()调用外,还可以通过其他的方式调用 。
function test(){
return "hello"
}
test.call() // "hello"
test.apply() // "hello"
/*
call 和 apply除了可以调用函数,还可以用来指定函数中的this
call和apply的第一个参数,将会成为函数的this
通过call方法调用函数,函数的实参直接在第一个参数后一个一个的列出来
*/
class User{
name = "l"
age = 18
}
function test(a,b){
console.log(this.name) // name
console.log(this) // User { name: 'l', age: 18 }
console.log(a) // 1
console.log(b) // 2
}
let user = new User()
// 指定test函数的this是user对象
test.call(user,1,2)
// 通过apply方法调用函数,函数的实参需要通过一个数组传递
class User{
name = "l"
age = 18
}
function test(a,b){
console.log(this.name) // name
console.log(this) // User { name: 'l', age: 18 }
console.log(a) // 1
console.log(b) // 2
}
let user = new User()
// 指定test函数的this是user对象
test.apply(user,[1,2])
bind() 是函数的方法,可以用来创建一个新的函数 。
- bind可以为新函数绑定this
- bind可以为新函数绑定参数
箭头函数没有自身的this,它的this由外层作用域决定 。
- 无法通过call apply 和 bind修改它的this
- 箭头函数中没有arguments
class User{
name = "l"
age = 18
}
function test(a){
console.log(a) // 10
console.log(this.name) // l
}
const user = new User()
// 指定新函数的this和参数,如果是原函数()调用,则走原函数的参数和this
const newFn = test.bind(user,10)
newFn()
最后此篇关于Js数组&高阶函数的文章就讲到这里了,如果你想了解更多关于Js数组&高阶函数的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!