JavaScript字符串、数组、对象方法总结
字符串方法
示例字符串:
const str = "hello,kitty,hello,vue ";
一、基本方法
charAt(n) 返回指定索引的字符 charCodeAt(n) 返回指定位置字符的Unicode编码 startsWith() 判断字符串是否以xxx开头,返回布尔值 endsWith() 判断字符串是否以xxx结尾,返回布尔值 padStart() 头部补全,返回新字符串 padEnd() 尾部补全,返回新字符串 repeat() 拷贝字符串,返回新字符串 toUpperCase() 大写转换,返回新字符串 toLowerCase() 小写转换,返回新字符串 trim() 去除首尾空格 trimStart()/trimLeft() 去除左边的连续空格 trimEnd() / trimRight() 去除右边的连续空格 repeat()
用例:
charAt() console.log(str.charAt(1)); // h trim() console.log(str.trim()); // hello,kitty,hello,vue startsWith() / endsWith() console.log(str.startsWith("hello")); // true padStart() / padEnd() str.padStart(number,string) 接收两个参数,第一个指定补全后的字符串长度,第二个可选,用来补全的字符串。默认补全空格 console.log(str.padStart(5,"x")); // hello,kitty,hello,vue 原本的长度超过了5,所以补不全 console.log(str.padStart(30,"x")); // xxxxxxxxhello,kitty,hello,vue 原本的长度少于30,缺多少补多少 console.log(str.padStart(30)); // hello,kitty,hello,vue repeat() str.repeat(number)接收一个参数,复制的份数 console.log(str.repeat(2)); // hello,kitty,hello,vue hello,kitty,hello,vue toUpperCase() / toLowerCase() console.log(str.toUpperCase()); // HELLO,KITTY,HELLO,VUE
二、字符串匹配
indexOf() 返回字符串中指定文本首次出现的索引,不存在返回-1 lastIndexOf() 返回字符串中指定文本最后一次出现的索引.如果不存在返回-1 search() 字符串内搜索特定值,返回第一次出现的索引,如果没有返回-1。与indexOf()的区别是,可以使用正则表达式, match() 字符串内检索指定的值,或找到一个或多个正则表达式的匹配。(通过字符串或正则表达式)。返回数组或null matchAll() 返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器 includes() 【es6新增】判断字符串中是否包含指定文本,返回布尔值
示例:
indexOf() / lastIndexOf() indexOf(string,start) 为匹配的字符串,start为开始匹配的索引,默认为0 console.log(str.indexOf("5")); // -1 console.log(str.indexOf("e")); // 1 search() console.log(str.search("o")); // 4 match() console.log(str.match("e")); // ["e"] 属性有:length,index,input console.log(str.match(/ell/g)); // ["ell","ell"] includes() console.log(str.includes("vue")); // true console.log(str.includes("react")); // false
三、字符串截取、分割:
substring() 根据索引截取字符串,返回新字符串 substr() 根据起始索引和长度截取。返回新字符串 slice() 根据索引截取,返回新字符串。与substring()不同的是,参数可以传入负值 trim() 去除首尾空格,返回新字符串 trimRight() 去除右侧空格,返回新字符串 trimLeft() 去除左侧空格,返回新字符串
用例:
substring() str.substring(start,end) 起始索引和结束索引。第一个参数必需,第二个非必需 console.log(str.substring(1)); // ello,kitty,hello,vue 从索引1开始到结束 console.log(str.substring(1,4)); // ell 从索引1到索引3的字符串 substr() str.substr(start,length) 传入一个开始索引和截取长度 console.log(str.substr(1,10)); // ello,kitty 从索引1开始截取长度为10的字符串 slice() str.slice(start,end) 根据索引,与substring不同的是,可以传入负值。如果参数为负值,表示从字符串的结尾开始计数。这里需要注意,如果传入负值,也遵从start在坐,end在右的规则。示例如下 console.log(str.slice(-7,-3)); // lo,v console.log(str.slice(-3,-7)); // 空
四、字符串分割、拼接
concat() 可拼接多个字符串,返回新的字符串 split() 将字符串分割成数组 join() 将数据转成字符串
用例:
let str1 = "abc",str2 = "def"; let arr = [1,2,3,4,5]; console.log(str.concat(str1,str2)); // hello,kitty,hello,vue abcdef console.log(str.split(",")); // ["hello", "kitty", "hello", "vue "] console.log(arr.join("-")); // 1-2-3-4-5
五、字符串替换
replace() 根据字符串或正则表达式进行替换,返回新字符串
用例:
let re = "/hello/g", re2 = "/hello/", re3 = "hello"; str.replace(re,"React"); // React,kitty,React,vue str.replace(re2,"React"); // React,kitty,hello,vue str.replace(re3,"React"); // React,kitty,hello,vue
数组方法
示例数组:
let arr = [1,2,3,4,5,6,7,8,9,10];
Array方法
Array.isArray() 判断对象是否为数组。 Array.of() 生成新的数组 Array.from() 将类数组或可迭代对象转化成数组,返回新数组,浅拷贝。
用例:
Array.from() 什么是类数组?有些对象,看上去很像数组,但不是array类型,不具有array的内置方法。例如querySelectorAll获取的元素列表。(实现相同的效果也可用延展操作符完成) let dom = document.querySelectorAll("li"); console.log(dom); console.log([...dom]); console.log(Array.from(dom)); let a = Array.from(["a","b","c"]) let b = Array.from([1,2,3],(x)=>{x+x}) // Array [2, 4, 6] Array.of() Array.of(5) // [5] Array.of(1,2,3) // [1,2,3]
元素的增删改(都会改变原数组)
增: push() 向数组的末尾添加一个或更多元素,并返回新的长度。 unshift() 向数组的开头添加一个或更多元素,并返回新的长度。 删: pop() 删除并返回数组的最后一个元素 shift() 删除并返回数组的第一个元素 copyWithin() 将数组中某几个元素复制到某一位置(浅拷贝),将原来被复制位置上的元素覆盖。该方法返回被改变的原数组。 splice() 可添加、删除、替换元素。 fill() 用一个固定值填充一个数组中指定范围内的元素
详细说明:
copyWithin() copyWithin(target,start,end) target是目标位置的索引,start是复制源的起始位置,end是结束位置。 三个参数都可以是负数,如果是负数,从末尾开始计算。后两个参数可选,如果start被忽略,将从0开始复制,如果end被忽略,将一直复制到数组结尾。 例如,将数组中第5个元素复制到第一个位置。将第5,6个元素复制到第1,2个位置。 console.log(arr.copyWithin(0, 4, 5)); // [5, 2, 3, 4, 5, 6, 7, 8, 9, 10] console.log(arr.copyWithin(0, 4, 6)); // [5, 6, 3, 4, 5, 6, 7, 8, 9, 10] splice() splice(start,number,items...) start为指定修改的开始位置,number为删除元素的个数,items数量不限表示要添加进数组的元素。该方法有返回值,不同的功能返回不同的内容。需要明确的是,此方法会改变原数组 删除: list.splice(0, 1) // 从下标为0开始,长度为1 list.splice(0, 2) // 从下标为0开始,长度为2 替换: list.splice(0, 1, 4); // 从下标为0开始,长度为1的数组元素替换成4 list.splice(0, 2, 4); // 从下标为0开始,长度为2的数组元素替换成4【两个元素被替换成一个元素】 添加: list.splice(1, 0, 5); // 在下标为1处添加一项5 list.splice(1, 0, 5, 4, 3); // 在下标为1处依次添加5/4/3三个元素 fill() fill(val,start,end) 后两个参数可省略 let array1 = [1, 2, 3, 4, 5]; console.log(array1.fill('a', 2, 5)); // [1, 2, "a", "a", "a"]
查找元素(非遍历)
includes() 判断数组是否包含某个值,返回布尔值。 slice() 根据索引从数组中返回选定的元素(浅拷贝) indexOf() 返回某元素在数组中首次出现的位置,不存在返回-1 lastIndexOf() 返回最后一次出现的位置,不存在返回-1
用例:
slice() slice(start,end) console.log(arr.slice(5,7)); // [6, 7]
数组遍历
传统for循环 forEach() 遍历数组,为所有元素调用一次回调函数。 map() 遍历数组,处理后返回一个新数组。如果回调函数内不返回,默认返回undefined数组。 flat() 递归遍历数组,将所有元素与遍历到的子数组中的元素合并为一个新数组返回。 flatMap() 首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 连着深度值为1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。 filter() 返回所有满足条件的元素,形成新数组。与map()的不同是,filter()只能返回元素,不能返回处理后的值。 find() 返回数组中满足条件的元素,只返回第一个。与filter()的不同是只返回第一个符合条件的元素。 findIndex() 返回数组中满足条件的元素的索引,只返回第一个。 some() 用于检测数组中的元素是否满足指定条件,只要有一个符合就返回true,结束循环。 every() 用于检测数组所有元素是否满足指定条件,一旦有一个不满足就返回false reduce() 从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。 reduceRight() 从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。
说明:
forEach() forEach((item,index,array)=>{}) 遍历数组,无法通过item修改原数组。 map() map((item,index,array)=>{}) 遍历数组,返回新数组,返回值由自己控制。 filter() filter((item,index,array)=>{}) 与map不同,该方法的作用是筛选元素。因此返回的数组中的项只能是原数组中的元素该方法将回调函数的返回值视为true和false,视为true时返回该元素。 find() find(...) flat([number]) 按照参数递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。number可选,指定要提取嵌套数组的结构深度,默认值为 1。返回值:新数组 var arr1 = [1, 2, [3, 4]]; arr1.flat() // [1, 2, 3, 4] var arr2 = [1, 2, [3, 4, [5, 6]]]; arr2.flat() // [1, 2, 3, 4, [5, 6]] var arr3 = [1, 2, [3, 4, [5, 6]]]; arr3.flat(2) // [1, 2, 3, 4, 5, 6] //使用 Infinity,可展开任意深度的嵌套数组 var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]; arr4.flat(Infinity) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] flatMap()
数组拼接、转换
concat() 连接两个或更多的数组,并返回结果。不会改变原数组 join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。 toString() 把数组转换为字符串,并返回结果。
数组的排序
sort() 对数组的元素进行排序,返回排序后的数组 reverse() 颠倒数组中元素的顺序。
用例:
sort() 默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的。 let points = [40, 100, 1, 5, 25, 10]; points.sort(); // [1, 10, 100, 25, 40, 5] 因此,有时需要我们自定义排序条件。回调函数中a,b两个参数是用来比较的两个元素,需要返回正值、0或负值。返回正值,a会排到b之前,返回0不改变相对位置,返回负值b排到a之前。 points.sort((a,b)=>{return a-b})); // [1, 5, 10, 25, 40, 100] points.sort((a, b)=》{return 0.5 - Math.random()}); // 随机排序
数组深拷贝
1.json序列化和反序列化
没错,这是个投机取巧的方法,简单粗暴,大部分基本类型都能都被有效拷贝。但也有一些弊端:像Maps,Sets,RegExps,Dates,ArrayBuffers和其他内置类型这样的东西以及undefined、函数在序列化时会丢失。
2.MessageChannel
通过构造函数MessageChannel()可以创建一个消息通道,实例化的对象会集成两个属性:port1和port2,这两个属性都是MessagePort对象。可以理解成电话两线的两端,都可以收发数据。
MessagePort
- 我们可以为其添加属性
let ms = new MessageChannel(); // 内含port1和port2 ms.port1.name = "Alex"; console.log(ms.port1);
- 可以看到,MessagePort还有两个属性onmessage和onmessageerror,他们都是接收到消息时的回调函数。
- 收发数据
port1.postMessage("发送数据"); port2.onmessage = (e) => {console.log("port2接收数据",e.data)}
回归正题,它除了可以用来通讯,还可以用作深拷贝,当然,拷贝函数对象的时候还是会报错。
3.loadsh,万全的深拷贝方案。
对象方法
示例对象:
let obj = { name: "hello", age: 20, func: ()=>{console.log("func")} }
原型方法(实例方法)
hasOwnProperty() 判断对象实例自身是否有某属性(不会找原型链上的属性)返回布尔值 isPrototypeOf() 检查一个对象是否存在于另一个对象的原型链上,返回布尔值 propertyIsEnumerable() 检测属性是否可枚举,返回布尔值 toLocaleString() 返回一个对象的字符串表示【直接调用toString()方法】 toString() 同上
示例:
obj.hasOwnProperty(prop) prop是否是obj的自有属性 obj.hasOwnProperty(name) // true obj.hasOwnProperty(names) // false a.isPrototypeOf(b) 检查a是否在b的原型链上 obj.prototype.isPrototypeOf(obj) // true Object.isPrototypeOf(obj) // true obj.propertyIsEnumerable(prop) 表示属性是否可枚举 obj.propertyIsEnumerable(age) // true obj.toLocaleString() / obj.toString() console.log(obj.toString()); // [object Object]
构造函数方法
Object.is() 判断两个值是否相同,与===基本一致,可以说是对其的完善 Object.assign() 复制、合并对象,返回新对象。(1.只会复制可枚举属性2.属性都是浅拷贝) Object.create() 创建一个新的对象,可以定义属性描述符。 Object.defineProperty() 在一个对象上定义/修改一个属性,返回这个对象。(同样可以定义属性描述符) Object.defineProperties() 在一个对象上定义/修改多个属性,返回这个对象 Object.keys() 返回一个对象的所有可枚举属性名称 Object.values() 返回一个对象的所有可枚举属性的值 Object.entries() 返回一个对象的所有可枚举属性的键值对数组(可以看做是上面两个方法的结合) Object.fromEntries() entries()的逆操作,用于将一个键值对列表还原为对象 Object.getOwnPropertyNames() 返回一个对象所有自身属性的名称(包括不可枚举属性但不包含Symbol属性名) Object.getOwnPropertySymbols() 返回一个对象的所有Symbol属性组成的数组(与上一个方法形成互补) Object.getOwnPropertyDescriptor() 返回对象的某一个自有属性的属性描述符 Object.getOwnPropertyDescriptors() 返回对象的所有自有属性的属性描述符 Object.seal() 封闭一个对象,阻止该对象添加新属性并将现有属性标记为不可配置(configurable),返回该对象 Object.isSealed() 判断一个对象是否已经封闭 Object.freeze() 冻结一个对象。这个对象不能新增、删出、修改属性,不可以修改属性描述符,其原型也不能被修改。返回该对象 Object.isFrozen() 判断对象是否已被冻结 Object.preventExtensions() 将一个对象变得不可扩展,永远不可以添加新的属性 Object.isExtensible() 判断对象是否可以扩展。seal()、freeze()、preventExtensions()都会使一个对象不可扩展 Object.getPrototypeOf() 返回指定对象的原型对象 Object.setPrototypeOf() 设置指定对象的原型对象
示例1:
Object.is(a, b) 比较两个值是否相等 与 == 的区别是:== 会做隐式类型转换,而is()不会 与 === 的区别是:=== 会将数字值 -0 和 +0 视为相等,并认为 Number.NaN 不等于 NaN Object.is("foo", "foo") // true Object.is({a:1}, {a:1}) // false Object.assign(target, ...source) 可将若干个source对象的自有可枚举属性整合到target对象上,返回target对象 Object.assign(obj, {a:1}, {b:2}, {name: "nihao"}) // { name: "hello", age: 20, func: ()=>{console.log("func")}, a: 1, b: 2 } Object.create(proto, descriptor) 创建一个新的对象,返回新的对象。参数proto是要继承的原型对象,descriptor是属性描述符。 Object.create(obj, a: { value: 1, writable:true, enumer:true, ableconfigurable:true }) Object.defineProperty(obj, prop, descriptor) 为一个对象创建一个属性 Object.defineProperty(obj, "a", {value: 1}) Object.defineProperties(obj, props) 为一个对象创建多个属性 Object.defineProperties(obj, { a: { value: 1, writable: true }, b: { value: 2. writable: false }, })
示例2:
Object.keys(obj) 返回一个对象的所有可枚举属性 Object.keys(obj) // [ "name", "age", "func" ] Object.values(obj) 返回一个对象的所有可枚举属性的值 Object.values(obj) // [ "hello", 20, f ] Object.entries(obj) 返回一个对象的所有可枚举属性的键值对数组 Object.entries(obj) // [ ["name", "hello"], ["age", 20], ["func", f] ] Object.formEntries(obj) 将键值对列表转化为对象,用途:array->object、map -> object Object.fromEntries([['foo', 'bar'],['baz', 42]]) // { foo: "bar", baz: 42 } const entries = new Map([['foo', 'bar'],['baz', 42]]); Object.fromEntries(entries) // { foo: "bar", baz: 42 } Object.getOwnPropertyNames(obj) 返回一个对象所有自身属性的名称(包括不可枚举属性但不包含Symbol属性名) Object.getOwnPropertyNames(obj) // ["name", "age", "func"] Object.getOwnPropertySymbols(obj) 返回一个对象的所有Symbol属性组成的数组(与上一个方法形成互补) Object.getOwnPropertySymbols(obj) // [] Object.getOwnPropertyDescriptor(obj, prop) 返回某对象的某个自有属性的描述符 Object.getOwnPropertyDescriptor(obj, "name") // { value: "hello", writable: true, enumerable: true, configurable: true } Object.getOwnPropertyDescriptor(obj, "age") // { value: 20, writable: true, enumerable: true, configurable: true } Object.getOwnPropertyDescriptors(obj) 返回某对象的所有自有属性的描述符
示例3:
Object.seal(obj) / Object.isSealed(obj) Object.freeze(obj) / Object.isFrozen(obj) Object.preventExtensions(obj) / Object.isExtensible(obj) Object.getPrototypeOf(obj) Object.setPrototypeOf(obj, prototype) prototype表示该对象新的原型(一个对象或null)