【JavaScript笔记 · 基础篇(七)】String全家桶(基本数据类型中的字符串 / String对象 / String.prototype)


一. 基本数据类型中的字符串

1.1 定义

字符串就是零个或多个排在一起的字符,放在单引号或双引号之中。通常用单引号 / 双引号 / 反引号括起来,或者结合嵌套使用。

var a = "hello world";//双引号
var a = 'hello world';//单引号
var a = `
     hello world
` ;//反引号(会打印出换行)  
var json = '{"name":"zevin","age":21}';//单双引号交替使用

分别的打印结果为:

hello world
hello world

  hello world

{"name":"zevin","age":21}

1.2 转义

反斜杠(\)在字符串内有特殊含义,用来表示一些特殊字符,所以又称为转义符。

  • \0 :null(\u0000)
  • \b :后退键(\u0008)
  • \f :换页符(\u000C)
  • \n :换行符(\u000A)
  • \r :回车键(\u000D)
  • \t :制表符(\u0009)
  • \v :垂直制表符(\u000B)
  • \ ’ :单引号(\u0027)
  • \ " :双引号(\u0022)
  • \ \ :反斜杠(\u005C)
console.log('Hi,I\'m zevin!');
// Hi,I'm zevin!

反斜杠还还有三种特殊的方法来表示特殊字符:

  • \HHH —— 反斜杠后跟三个八进制数(000到377),最多可表示256种字符;
  • \xHH —— 反斜杠后跟十六进制数(00到FF),最多可表示256种字符;
  • \uHHHH —— 反斜杠后跟四个十六进制数(0000到FFFF);

比如版权符号(©)的表示:

'\251' // "©"
'\xA9' // "©"
'\u00A9' // "©"

'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true

反斜杠也支持自身转义:

"Left \\ Right"
// "Left \ Right"

1.3 字符串与数组

字符串与数组有一个很相似的地方,就是都可以通过方括号运算符来访问某个位置的字符。

var str = 'zevin';
str[0] // "z"
str[1] // "e"
str[3] // "i"

// 直接对字符串使用方括号运算符
'zevin'[1] // "e"

如果方括号中的数字超过字符串的长度,或者方括号中根本不是数字,则返回undefined

'abc'[3] // undefined
'abc'[-1] // undefined
'abc'['x'] // undefined

1.4 length 属性

length属性返回字符串的长度。

var s = 'hello';
s.length // 5

同样该属性也是无法改变的,但是也不会报错。

s.length = 3;
s.length // 5

s.length = 7;
s.length // 5

二. String对象

2.1 概述

String对象也是 JavaScript 原生提供的三个包装对象之一,用来生成字符串对象的构造函数。

var s1 = 'abc';
var s2 = new String('abc');

typeof s1 // "string"
typeof s2 // "object"

同时字符串对象也是四大类数组对象之一。并不是真正的数组。

new String('abc')
// String {0: "a", 1: "b", 2: "c", length: 3}

'abc'[1] // 'b'
'abc'.length // 3

'abc' instanceof Array // false

除了用作构造函数,String对象还可以当作工具方法使用,将任意类型的值转为字符串。

String(true) // "true"
String(5)    // "5"

2.2 静态方法 —— String.fromCharCode()

fromCharCode()方法的参数是一个或多个数值,代表 Unicode 码点,返回值是这些码点组成的字符串。

String.fromCharCode() // ""
String.fromCharCode(97) // "a"
String.fromCharCode(104, 101, 108, 108, 111)
// "hello"

2.3 实例属性 —— String.prototype.length

字符串实例的length属性返回字符串的长度。

'abc'.length // 3

三. String.prototype.*

由于字符串对象本质为类数组对象,所以String对象有很多和Array对象同名的原型实例方法,比如:concat(),indexOf(),lastIndexOf(),slice()等等。

3.1 与正则表达式相关

字符串对象的原型实例方法中,有很多都可以接受一个正则表达式作为参数。

String.propertype.split()

split方法按照给定规则(某个字符或正则表达式)分割字符串,返回一个由分割出来的子字符串组成的数组。

  • 参数:(string/regexp,num)
    • string/regexp(必须) —— 分割符,分割字符串的依据;
    • num(非必须)—— 限定返回数组的最大成员数;
  • 返回值:数组
  • 原值:不改变
let str = "zevin#code";

console.log(str.split(""));
console.log(str.split(/\#/));
console.log(str);


——————OUTPUT——————
[
  'z', 'e', 'v', 'i',
  'n', '#', 'c', 'o',
  'd', 'e'
]
[ 'zevin', 'code' ]
zevin#code

还要注意的是,split()方法分割字符串时会出现空字符串的情况,比如:原字符串中存在两个相邻的分割字符,或者分割字符位于原字符串的开头或结尾。

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

split方法还可以接受第二个参数,限定返回数组的最大成员数。

'a|b|c'.split('|', 0) // []
'a|b|c'.split('|', 1) // ["a"]
'a|b|c'.split('|', 2) // ["a", "b"]
'a|b|c'.split('|', 3) // ["a", "b", "c"]
'a|b|c'.split('|', 4) // ["a", "b", "c"]
String.propertype.search()

search()用于子串的匹配查找,返回该子串在原字符串中第一次匹配的位置。如果没有找到,则返回 -1。

  • 参数:(string/regexp)
    • string/regexp(必须) —— 子串
  • 返回值:正数(n >= 0 || n = -1)
  • 原值:不改变
"zevincode".search('e')  // 1
"zevincode".search(/e/)  // 1
"zevincode".search(/a/)  // -1
String.propertype.match()

match方法用于确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的第一个字符串。如果没有找到匹配,则返回null。

  • 参数:(string/regexp)
    • string/regexp(必须) —— 子串
  • 返回值:数组或null
    • index —— 匹配字符串开始的位置
    • input —— 原始字符串
  • 原值:不改变
"zevincode".match('e')  // ["e"]
"zevincode".match(/hello/)  // null

返回的数组还有index属性和input属性,分别表示匹配字符串开始的位置和原始字符串。

var matches = "zevincode".match('e');
matches.index // 1
matches.input // "zevincode"

所以match方法的返回值的index属性和search方法的作用是一致的。

"zevincode".match('e').index === "zevincode".search('e')
// true
String.propertype.replace()

replace方法用于替换匹配的子字符串,一般情况下只替换第一个匹配(除非使用带有g修饰符的正则表达式)。

  • 参数:(string/regexp,replacestr)
    • string/regexp(必须) —— 需要替换的子串;
    • replacestr(必须)—— 要替换为的字符串;
  • 返回值:替换后的结果字符串
  • 原值:不改变
'zevincode'.replace('z', 'k') // "kevincode"

❀ 拓展一下❀

还有一个小技巧,replace方法还可以用来在原字符串内符合匹配规则的子串前后添加字符。需要用到$1的位置标识。比如金融数字表示法(三位一个逗号间隔):

1384125862..toString().replace(/(\d)(?=(?:\d{3})+$)/g,"$1,")
// 1,384,125,862

该正则表达式匹配的正是每三位数中的那个末位数字。"$1,"表示在子串之后添加逗号

1384125862..toString().match(/(\d)(?=(?:\d{3})+$)/g)
// [ '1', '4', '5' ]

有关金融数字表示法(三位一个逗号间隔)的更多实现方式,感兴趣的可以去看:

【面试题集 —— No.06】数字格式转化问题 —— 金融数字样式:千位分隔符(三位一个逗号间隔)


3.2 遍历检索

String.prototype.indexOf(),String.prototype.lastIndexOf()

indexOf方法用于确定一个字符串在另一个字符串中第一次出现的位置,返回结果是匹配开始的位置。如果返回-1,就表示不匹配。

  • 参数:(string,begin)
    • string(必须) —— 需要匹配的子串;
    • begin(非必须)—— 指定开始检索的位置;
  • 返回值:正数(n >= 0 || n = -1)
  • 原值:不改变
"zevincode".indexOf('code')   // 5
"zevincode".indexOf('hello')  // -1

"zevincode".indexOf('e',5)  // 8

lastIndexOf方法的用法跟indexOf方法一致,主要的区别是lastIndexOf从尾部开始匹配,indexOf则是从头部开始匹配。

"zevincode".lastIndexOf('code')   // 5
"zevincode".lastIndexOf('hello')  // -1

"zevincode".lastIndexOf('e',5)  // 1

要注意的是,lastIndexOf只是匹配的顺序改成了从后往前,但是每个字符的具体位置还是没有变的。

3.3 截取子串

String.prototype.slice()

slice()方法用于从原字符串取出子字符串并返回,不改变原字符串。它的第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。

  • 参数:(begin,end)
    • begin(必须) —— 子串的开始位置;
    • end(非必须)—— 子串的结束位置(不含该位置);
  • 返回值:子字符串(可能为空串)
  • 原值:不改变

如果省略第二个参数,则表示子字符串一直到原字符串结束。

'zevin'.slice(2,3)  // v
'zevin'.slice(2)    // vin

如果参数是负值,表示从结尾开始倒数计算的位置,即该负值加上字符串长度。

'JavaScript'.slice(-6) // "Script"
'JavaScript'.slice(0, -6) // "Java"
'JavaScript'.slice(-2, -1) // "p"

如果第一个参数大于第二个参数(正数情况下),slice()方法返回一个空字符串。

'JavaScript'.slice(2, 1) // ""
String.prototype.substring()

substring()方法与slice()方法的用法很类似,也是截取子串并返回。

  • 参数:(begin,end)
    • begin(必须) —— 子串的开始位置;
    • end(非必须)—— 子串的结束位置(不含该位置);
  • 返回值:子字符串
  • 原值:不改变
'JavaScript'.substring(0, 4) // "Java"
'JavaScript'.substring(4) // "Script"

他俩的区别在于:如果第一个参数大于第二个参数,slice方法直接返回null;而substring方法会自动更换两个参数的位置。

'JavaScript'.substring(10, 4) // "Script"
// 等同于
'JavaScript'.substring(4, 10) // "Script"

而且在substring方法还有把负数转换成0的设定:

'JavaScript'.substring(-3) 
// 等同于
'JavaScript'.substring(0)  // "JavaScript"

这样就会出现一些非常奇怪的结果,比如这个:

'JavaScript'.substring(4, -3) // "Java"

简单分析一下:首先第二个参数为负,先转换成0,然后又由于第一个参数大于第二个参数(4 > 0),所以会继续交换两者位置:

'JavaScript'.substring(4, -3) // "Java"
// 等同于
'JavaScript'.substring(4, 0) // "Java"
// 等同于
'JavaScript'.substring(0, 4) // "Java"

这样的设定就略显繁琐了,还是推荐使用slice方法。

String.prototype.substr()

substr方法的作用还是截取字符串,与slicesubstring是三胞胎,它们之间略有区别:substr方法的第二个参数不再是结束的位置了,而是子字符串的长度。

  • 参数:(begin,length)
    • begin(必须) —— 子字符串的开始位置;
    • length(非必须) —— 子字符串的长度;
  • 返回值:子字符串(可能为空串)
  • 原值:不改变
'JavaScript'.substr(4, 6) // "Script"
// 等同于
'JavaScript'.substr(4) // "Script"

如果第一个参数是负数,表示倒数计算的字符位置。如果第二个参数是负数,将被自动转为0,因此会返回空字符串。

'JavaScript'.substr(-6) // "Script"
'JavaScript'.substr(4, -1) // ""

3.4 大小写转换

String.prototype.toLowerCase(),String.prototype.toUpperCase()

toLowerCase方法用于将一个字符串全部转为小写,toUpperCase则是全部转为大写。它们都返回一个新字符串,不改变原字符串。

  • 参数:(string)
    • string(必须) —— 需要转化的字符串;
  • 返回值:新字符串
  • 原值:不改变
'Hello World'.toLowerCase()
// "hello world"

'Hello World'.toUpperCase()
// "HELLO WORLD"

这两个方法常用于不分大小写的字母排序问题

当数组元素均为大小写不同的英文字母时,按照sort()默认的字典顺序(ASCII码值)会出现大写在前,小写在后的顺序。如何进行不区分大小写的正确排序呢 ?

var arr = ['Z','e','V','I','n'];
console.log(arr.sort());


——————OUTPUT——————
[ 'I', 'V', 'Z', 'e', 'n' ]

不区分大小写就需要我们在比较器函数中多写一步全大写(小写)的转换过程,然后再按值排序。

var arr = ['Z','e','V','I','n'];
arr.sort(function(a, b){
    var x = a.toLowerCase(), y = b.toLowerCase();
    return x < y ? -1 : x > y ? 1 : 0;
});
console.log(arr);


——————OUTPUT——————
[ 'e', 'I', 'n', 'V', 'Z' ]

3.5 其他

String.prototype.trim()

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

  • 参数: 无
  • 返回值:新字符串
  • 原值:不改变
'  hello world  '.trim()
// "hello world"
String.prototype.concat()

concat方法用于连接两个字符串,返回一个新字符串,不改变原字符串。

  • 参数:(str1,str2,str3…)
  • 返回值:新字符串
  • 原值:不改变
var s1 = 'abc';
var s2 = 'def';

s1.concat(s2) // "abcdef"

该方法可以接受多个参数。

'a'.concat('b', 'c') // "abc"

如果参数不是字符串,concat方法会将其先转为字符串,然后再连接。

var one = 1;
var two = 2;
var three = '3';

''.concat(one, two, three) // "123"
one + two + three // "33"
String.prototype.charAt()

charAt方法返回指定位置的字符,与数组的中括号访问符作用一致:

  • 参数:(index)
    • index(必须)—— 字符位置下标;
  • 返回值:指定位置的字符或空字符串
  • 原值:不改变
'abc'.charAt(1) // "b"
'abc'[1]        // "b"

如果参数为负数,或大于等于字符串的长度,charAt返回空字符串。

'abc'.charAt(-1) // ""
'abc'.charAt(3) // ""
String.prototype.charCodeAt()

charCodeAt()方法返回字符串指定位置的 Unicode 码点(十进制表示),相当于String.fromCharCode()的逆操作。

  • 参数:(index)
    • index(非必须)—— 字符位置下标;
  • 返回值:指定位置字符的Unicode 码点 / null
  • 原值:不改变
'abc'.charCodeAt(1) // 98

如果没有任何参数,charCodeAt返回首字符的 Unicode 码点。

'abc'.charCodeAt() // 97

如果参数为负数,或大于等于字符串的长度,charCodeAt返回NaN

'abc'.charCodeAt(-1) // NaN
'abc'.charCodeAt(4) // NaN

常用总结

这么多有关字符串对象的API,需要重点掌握的我觉得有split()slice()concat()toUpperCase()replace()match()等等。

每一个不曾起舞的日子,都是对生命的辜负!

—— 尼采

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值