基础:字符串、数组

325 阅读7分钟

一、字符串基础

字符串是类数组对象,可以通过索引访问、有length属性,但不能改变字符串内的单个字符,用 + 可以连接多个字符串。因为 html 属性值使用双引号,建议字符串使用单引号

let str = 'hello' + ' ' + 'world';

1. String 和 toString 的区别

String 可以将任意类型的值转为字符串。 toString 原来是 Object 上定义的方法,之后 Array、Number 做继承后又重新定义了自己的 toString,覆盖了 Object 上的。像 null、undefiend 等类型上没有定义 toString 方法,所以调用时会出错。

  • String():将参数转为字符串,null -> 'null'undefined -> 'undefined'
  • a.toString():需要看 a 的类型,该类型是否定义了该 toString 实例方法,以及返回的应该是什么含义的字符串。例如:
    • Object.prototype.toString:返回一个对象的类型字符串。
    • Array.prototype.toString:返回数组的字符串形式,并且会拉成一维字符串'1, 2, 3',String函数也会。
    • Number.prototype.toString:将数值转为字符串形式。
String(5);  // '5'

二、字符串的实例方法

1. ES5 的实例方法

1. charCodeAt

charCodeAt 返回字符串指定位置字符的 Unicode码点(十进制表示),越界则返回 NaN。

'abc'.charCodeAt(0)  // 97

2. concat

连接个字符串,返回一个新的字符串,不改变原字符串,用+更加方便。

let s1 = 'hello', s2 = 'world';
let str = s1.concat(s2);
str  // 'helloworld'

3. slice 和 substr:提取子串

slicesubstr 都是从 原字符串取出子串并返回该子串,不改变原字符串

str.slice(start, end);  // 不包括 end 位置
str.substr(start, length);
// slice
'JavaScript'.slice(4)  // 'Script'  只有 1 个参数,则表示一直到字符串结束
'JavaScript'.slice(0, -6)  // 'Java'   负值表示倒数
'JavaScript'.substr(4)  // 'Script'  同 slice

4. split:字符串 --> 数组

按照给定规则分割字符串,返回一个数组。参数如果为空字符,则返回每个字符;如果为空,则返回一个字符串。

'a|b|c'.split('|')  // ['a', 'b', 'c']
'a|b|c'.split('')   // ['a', '|', 'b', '|', 'c']
'a|b|c'.split()  // ['a|b|c']

5. indexOf / lastIndexOf

正数(倒数)查找一个字符串在另一个字符串第一次出现的位置,能找到就返回位置,找不到就返回 -1第 2 个参数(可选)表示从该位置向后(前)匹配

注意:JS 是区分大小写的!

'hello'.indexOf('ll')  // 2
'hello'.indexOf('Hello')  // -1

6. toLowerCase / toUpperCase

返回新的字符串,不改变原字符串。

'Hello World'.toLowerCase()  // "hello world"
'Hello World'.toUpperCase()  // "HELLO WORLD"

7. trim

去除两端的空格,返回一个新的字符串,不改变原字符串。

' hello world  '.trim()   // 'hello world'

8. match/search/replace/split:用于正则表达式

2. ES6 新增实例方法

1. includes

indexOf一样,都是在一个字符串中查找另一个字符串,区别在于 返回值是布尔值,表示是否找到了参数字符串,第 2 个参数表示开始搜索的位置

'hello'.includes('o');

2. repeat

repeat() 返回一个字符串,表示将原字符串重复 n 次。

'nice'.repeat(2);  // 'nicenice'
'hello'.repeat(0);  // ''
'hello'.repeat(2.9);  //'hellohello' ,参数的小数的话会取整
  • 参数是小数,则取整;是NaN,则相当于 0。
  • 参数是 负数 或 Infinity,会报错。

3. ES6 模板字符串

模板字符串是增强版的字符串,用反引号标识。它可以当作普通字符串,也可以用来定义多行字符串,或者在字符串中嵌入变量。

  • 所有的空格、缩进都会保留
  • 需要嵌入变量时,将变量名写在 ${}
  • 大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。
`In JavaScript this is
 not legal.`

`User ${user.name} is not authorized to do ${action}.`

`${x} + ${y} = ${x + y}`

三、字符串总结

  1. 字符串的所有实例方法都不会改变原字符串(因为字符串不能改变单个字符)。
  2. concat、slice、substr、toLowerCase、toUpperCase、trim、repeat 都会返回新的字符串
  3. indexOf 返回位置索引,找不到则 -1。charCodeAt 返回Unicode 码点(十进制表示),越界则 NaN。includes 返回布尔值
  4. JS 是区分大小写的。

四、ES5 数组的静态和实例方法

算法题常用到的知识点:初始化二维数组的方法

1. 静态方法 Array.isArray()

Array.isArray 判断参数是否为数组,返回布尔值。可以弥补 typeof 的不足。

2. 实例方法

1. push / pop / shift / unshift:会改变原数组。

  • push: 数组末端添加一个或多个元素,返回新数组的长度

  • pop:删除数组的最后一个元素,返回该元素

  • shift:删除数组的第一个元素,返回该元素

  • unshift:在数组的第一个位置添加一个或多个元素,返回新数组的长度

2. concat / slice / indexOf / lastIndexOf:字符串也有,不改变原数组

(1)concat 同字符串,而且参数可以是对象、数组或其他值,不改变原数组。

[1, 2].concat([3, 4]);  // 新数组 [1, 2, 3, 4]
[1, 2].push([3, 4]);  // [1, 2, [3, 4]]

注意:数组成员中含有对象,那么使用concat()会返回当前数组的一个浅拷贝

let newArray = objArray.concat()

(2)slice 同字符串,如果没有参数,则返回的是原数组的拷贝

[1, 2, 3].slice()  // [1, 2, 3]

重要应用是,可以转换类数组Array.prototype.slice.call()

(3)indexOf 同字符串,另外注意 indexOf 不能用来搜索 NaN,因为内部使用的是严格相等运算符, NaN 不等于自身(相等或严格相等都不满足)。

3. splice:改变原数组

用于删除原数组的一部分成员,并且可以在删除的位置添加新的成员,返回值是被删除的元素/数组

arr.splice(start, length, add1, add2, ...)   // 和 slice的第 2 个参数不同

可以插入元素:第 2 个参数设置为0。

arr.splice(start, 0, add1, add2,...)  

可以拆分成两个数组:只提供一个参数。

let a = arr.splice(start);  // 拆分出的两个数组就是 a 和 arr

4. sort:改变原数组

默认按照字典序排列,也就是 101 < 11所以使用时务必要传参

ES2019 规定,sort 排序的算法必须是稳定的。

a.sort((a, b) => a - b);  // 升序
a.sort((a, b) => b - a);  // 降序

详见 sort的内部算法

5. join

将数组成员连接成一个字符串并返回,并且字符串之间用给定参数作分隔符参数为空时默认用逗号分隔

  • join('') 和 split(''):常用的转换方式。
  • join() 和 split():字符串之间用逗号分隔。数组成员只有唯一的一个字符串。

注意:一般都是用空字符

const arr = ['a', 'b', 'c'];
arr.join('');  // 'abc'
arr.join();  // 'a, b, c'

6. reverse:改变原数组

颠倒数组,返回改变后的数组,会改变原数组

7. map / forEach / filter / reduce / reduceRight:不改变原数组

详细可见 手写源码

  • map、filter:返回一个数组。
  • reduce:返回累计值。
  • forEach:没有返回值。

「push四件套、splice、sort、reverse 都改变原数组。」

8. some、every 断言

传参和 map一样,返回的是布尔值

  • some:只要一个成员的返回值是 true,那么就返回 true。
  • every:所有成员的返回值都是 true,才返回 true。

五、ES6 数组的静态和实例方法

1. 扩展运算符...

数组转换为一个用逗号分隔的参数序列,可用于:

  • 求最值
Math.max(...arr)   // ...后跟数组

2. Array.from

用于将 伪数组转为真正的数组

3. fill

使用给定值,填充一个数组。第二个、第三个参数用于指定 填充的开始和结束位置,不包括结束位置。

一般来说,编程思想遵循 左闭右开 的准则,因此结束位置的元素不会被包含。

new Array(3).fill(7)  // [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2)  // ['a', 7, 'c']

4. find / findIndex

find 找到符合条件的元素并返回,找不到返回undefinedfindIndex类似 indexOf,找到符合条件的元素索引,找不到也会返回 -1

注意:与 indexOf 不同,find 和 findIndex 可以找到 NaN。

5. flat

手撕源码:flat

6. includes

同ES6的 字符串新增方法。