JavaScript字符串所有API解密

截止到es6,字符串共包含31个标准的API方法,其中有些方法出镜率较高,需要摸头原理;有些方法相似度较高,需要仔细分辨;甚至有些方法执行效率较低,应当尽量少的使用。

String构造器方法

String.fromCharCode()

静态String.fromCharCode() 方法返回由指定的UTF-16代码单元序列创建的字符串。
语法 fromCharCode(num1, num2, ...)传入的参数均为数字。

示例:

lua复制代码console.log(String.fromCharCode(189,43,190,61))

expected output: '½+¾='

actual output: '½+¾='

方法缺陷:只能处理UCS-2编码,即所有字符都是2个字节,无法处理4字节字符。为了弥补这个缺陷,ES6新增了fromCodePoint方法。

String.formCodePoint()

string.fromCodePoint() 静态方法返回使用指定的代码点序列创建的字符串。作用和语法同fromCharCode()方法,该方法主要扩展了对4字节字符的支持。

arduino复制代码// '𝌆'是一个四字节字符,
'𝌆'.codePointAt()  // 119558
// 调用fromChartCode()解析,返回乱码
String.fromCharCode(119558);  // '팆'
// 调用fromCodePoint(),正常解析
String.fromCodePoint(119558); // '𝌆'

String.raw()

raw()方法基于ES6规范,它是一个模板字符串的标签函数,作用类似于python的r和c#的@字符串前缀,都是用来获取一个模板字符串的原始字面量。
语法:String.raw(callSite, ...substitutions),callSite即模板字符串的调用点对象,...substitutions表示任意个内插表达式对应的值。

如下是python的字符串前缀r:

python复制代码# 防止特殊字符串被转义
print r'a\nb\tc' # 打印出来依然是 'a\nb\tc'
# python中常用语正则表达式
regExp = r'(?<=123)[a-z]+'

如下是String.raw作为前缀的用法:

javascript复制代码// 防止特殊字符串被转义
String.raw`a\nb\tc`  输出为'a\nb\tc'
// 支持内插表达式
let name = 'louis'
String.raw`Hello \n ${name}`
// 内插表达式还可以运算
String.raw`1+2=${1+2},2*3=${2*3}` // '1+2=3,2*3=6'

String.raw作为函数来调用的场景不太多,如下是用法:

arduino复制代码// 对象raw属性值为字符串时,从第二个参数起,他们分别被插入到下标为0,1,2,...n的元素后面
String.raw({raw: 'abcd'},1,2,3) // a1b2c3d
// 对象raw属性值为数组时,从第二个参数起,他们分别被插入到数组下标为0,1,2,...n的元素后面
String.raw({raw: ['a', 'b', 'c']}, 1,2,3) // a1b2c3d

怎么解释String.raw函数按照下标挨个去插入的特性,MDN是这么描述的:

vbnet复制代码In most case,String.raw() is used with templates string.The first syntax mentioned above is only rarely used,because the JavaScript engine will call this with proper arguments for you,just like with other tag functions.

这意味着,String.raw作为函数调用时,基本与ES6的tag标签模板一样,如下:

javascript复制代码function tag() {
    const ary = arguments[0]
    return ary.reduce((pre, cur, index) => {
        pre + (argument[index] || '') + cur
    })
}

tag`Hello ${2+3} world ${2*3}` // hello 5 world 6
tag(['hello, 'world', ''], 5, 6) // hello 5 world 6

因此String.raw作为函数调用时,不论对象的raw属性值是字符串还是数组,插槽都是天生,下标0,1,2,...n的元素后面都是插槽(不包括最后一个元素)。实际上,它相当于是这样的tag函数:

javascript复制代码function tag() {
    const ary = arguments[0].raw
    if (ary === undefined || ary === null) { // 这里可以简写成 ary == undefined 或者 !ary
        throw new TypeError('Cannor convert undefined or null to object')
    }
    return ary.reduce((pre, cur, index) => {
        pre + (arguments[index] || '') + cur
    })
}

实际上,String.raw作为函数调用时,若第一个参数不是一个符合标准格式的对象,执行将跑出TypeError错误。

String.raw({123: 'abcd'}, 1,2,3) // TypeError: Cannot convert undefined or null to object

目前只有Chrome v41 和 Firefox v34版本浏览器实现了该方法。

String.prototype

和其他所有对象一样,字符串实例的所有方法均来自String.prototype。以下是它的属性特性:

属性

writable

false

enumerable

false

configurable

false

可见,字符串属性不可编辑,任何试图改变它属性的行为都将抛出错误。

属性

String.prototype共有两个属性,如下:

  • String.prototype.constructor 指向构造器(String())
  • String.prototype.length 表示字符串长度
    方法
    字符串原型方法分为两种,一种是html无关的方法,一种是html有关的方法。但无能字符串方法如何厉害,都不至于强大到可以改变原字符串。

HTML无关的方法

常用的方法有,charAt、 charCodeAt 、 concat 、indexOf 、lastIndexOf 、localeCompare 、match 、replace 、search 、 slice 、split 、substr 、substring 、toLocaleLowerCase 、toLocaleUpperCase 、 toLowerCase 、toString 、toUpperCase 、trim、 valueof等ES5支持的,以及codePointAt 、contains 、endsWith 、startsWith、 normalize 、 repeat 、normalize等ES6支持的,还包括quote 、toSource 、trimLeft 、 trimRight等非标准的。

String.charAt():返回字符串中指定位置的字符

语法:str.charAt(index)
index为字符串索引,取值从0至length - 1,如果超出该范围,则返回空串。

console.log('Hello, World'.chatAt(8)) // o,返回下标为8的字符串o

String.charCodeAt():返回指定索引处字符的Unicode数值

语法:str.charCodeAt(index)

  • index为一个从0之length-1的整数。如果不是一个数值,则默认为0,如果小于0或者大于字符串长度,则返回NaN。
  • Unicode编码单元(code points)的范围从0到1,114,111。开头的128个Unicode编码单元和ASCII字符编码一样。
  • charCodeAt()总是返回一个小于65,536的值。因为高位编码单元需要由一堆字符来表示,为了查看其编码的完成字符,需要查看charCodeAt(i)以及charCodeAt(i+1)的值。
arduino复制代码console.log('Hello,World'.charCodeAt(8)) // 111
console.log('前端工程师'.charCodeAt(2)) // 24037,可见中文Unicode编码

String.concat: 将一个或者多个字符串拼接在一起,组成心的字符串并返回。

语法:str.concat(str1,str2, ...)

console.log('早'.concat('上', '好')) // 早上好
但是concat的性能表现不佳,强烈推荐使用赋值操作符(+或=)代替concat。'+'操作服大概快了concat几十倍。

indexOf/lastIndexOf :

indexOf: 用于查找字符串在字符串中首次出现的位置,没有则返回-1.该方法严格区分大小写,而且从左往右查找。而lastIndexOf则从右向左查找,其它与前者一致。

语法:str.indexOf/latIndexOf(searchValue[,fromIndex=0])
searchValue表示被查找的字符,fromIndex表示开始查找的位置,默认为0,如果小于0,则查找整个字符串,若超过字符串长度,则该方法返回-1,除非被查找的是空字符串,此时返回字符串长度。

javascript复制代码console.log(''.indexOf('', 100)) // 0
console.log('IT改变世界'.indexOf('世界')) // 4
console.log('IT改变世界'.lastIndexOf('世界')) // 4

String.localeCompare: 比较字符串,如果指定字符串在原字符串的前面则返回负数,否则返回正数或0,其中0表示两个字符串相同。该方法实现依赖具体的本地实现,不同的语言下可能有不同的返回。

语法:str.localeCompare(str, [,locales[,options]])

javascript复制代码let str = 'apple'
let str2 = 'orange'
console.log(str.localeCompare(str2)) // -1
console.log(str.localeCompare('123')) // 1

目前Safari浏览器不支持该方法,但Chromev24 、Firefoxv29+、IE11和Operav15+都已实现。

String.match: 测试字符串是否支持指定正则表达式的规则,即使传入的是非正则表达式对象,他也会隐式的使用new RegExp(obj)将其转换为正则表达式对象。

语法:str.match(regexp)

该方法返回包含匹配结果的数组,如果没有匹配项,则返回null;

描述

  • 若正则表达式没有g标志,则返回RegExp.exec(str)相同的结果。而且返回的数组拥有一个额外的input属性,该属性包含原始字符串,另外该数组还拥有一个index属性,该属性表示匹配字符串在原富川中索引(从0开始)。
  • 若正则表达式包含g标志,则该方法返回一个包含所有匹配结果的数组,没有匹配到则返回null。

相关RegExp方法

  • 若需测试字符串是否匹配正则,青草考RegExp.test(str)
  • 若只需第一个匹配结果,请参考RegExp.exec(str)。
javascript复制代码let str = 'World Internet Conference'
console.log(str.match(/[a-d]/i)) // ['d', index: 4, input: 'World Internet Conference']
console.log(str.match(/[a-d]/gi)) ['d', 'C', 'c']
// RegExp 方法如下
console.log(/[a-d]/gi.test(str)) // true
console.log(/[a-d]/gi.exec(str)) // ['d', index: 4, input: 'World Internet Conference']

由上可知,RegExp.test(str)方法只要匹配到了一个字符串也返回true。而RegExp.exec(str)方法无论正则中有没有包含g标志,RegExp.exec将直接返回第一个匹配结果,且该结果同str.match(regexp)方法不包含g标志时的返回一致。

String.replace: 不改变自身,返回替换后的字符串。

语法:str.replace(regexp | substr, newSubStr | function[,flags])

参数:第一个参数是需要替换的字符串或者正则表达式,第二个是新的字符串或者一个function,从字面中可以看出共有四种组合。

  • regexp: 一个RegExp对象,该正则所匹配的内容会被第二个参数的返回值替换掉。
  • subStr: 一个要被newSubStr替换的字符串。
  • newSubStr: 替换掉第一个参数在原字符串中的匹配部分,该字符串中可以内插一些特殊的变量名。
  • function:一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果。
  • flags: 注意:flags参数在v8内核(chrome and nodejs)中不起作用,方法中使用flags参数是不符合标准的并且不赞成这样做。

描述:该方法并不改变调用它的字符串本身,而只是返回替换后的字符串。

DEMO
1。一般来说,我们使用js String对象的replace方法的姿势是这个样子的:

match1: String -> String

ini复制代码let a = 'what is this? before';
let b = a.replace('before', 'after');
console.log(b)

仅仅用到了文本替换问文本的功能。

2。更高级的还可以摆出这样的姿势,如果第一个参数是正则表达式,新的字符串中可以用$符号取正则中匹配的字符串(也就是正则中被括号包裹的部分):

match2: RegExp -> String

javascript复制代码let a = 'what is this? before'
let b = a.replace(/(^\w+).*?(\w+)$/, '$2 $1') // 括号分割的部分依次为子串1...n
console.log(b) // bofore what

等等用法。

String.search(): 测试字符串对象是否包含某个正则匹配,相当于正则表达式的test方法,且该方法比match()方法更快。如果匹配成功,search()返回正则表达式在字符串中首次匹配项的索引,否则返回-1.

注意:search和indexOf方法作用基本一致,都是查询到了就返回淄川第一次出现的下标,否则返回-1,唯一的区别就在于search默认会将子串转化为正则表达式形式,而indexOf不做此处理,也不能处理正则。

语法:str.replace(regexp)

javascript复制代码const STR = 'abcdefg'
console.log(str.search(/[d-g]/)) // 3,匹配到子串'defg',而d在原字符串中的索引为3

search()方法不支持全局匹配(正则中包含g参数), 如下:

console.log(str.search(/[d-g]/g)); // 3,与无g参数时,返回相同

slice: 提取字符串的一部分,并返回新的字符串。该方法有些类似Array.prototype.slice方法。

语法: str.slice(start, end)

  • 首先end参数可选,start可取正值,也可取负值。取正值时表示从索引为start的位置截取到end的位置(不包括end所在位置的字符,如果end省略则截取到字符串末尾)。
  • 取负值时表示从索引为length+start位置截取到end所在位置的字符
rust复制代码const str = 'It is our choice that show what we truly are, far more than our abilities.'
console.log(str.slice(0, -30)) // It is our choices that show what are truly are

console.log(str.slice(-30)) // ,far more than our abilities.

String.split: 把原字符串分割成字符串组成数组,并返回该数组。

语法:str.split(separator, limit)
两个参数均是可选的,其中separator表示分隔符,它可以是字符串也可以是正则表达式。如果忽略separator,则返回的数组包含一个由原字符串组成的元素。如果separator是一个空船,则str将会被分割成一个由原字符串中字符组成是的数组。limit表示从返回的数组中截取前limit个元素,从而限定返回的数组长度。

python复制代码const str = 'today is sunny day'
console.log(str.split()) // [today is a sunny day]
console.log(str.split('')) //  ['t', 'o', 'd', 'a', 'y', ' ', 'i', 's', ' ', 'a', ' ', 's', 'u', 'n', 'n', 'y', ' ', 'd', 'a', 'y']
console.log(str.split(" ")) // ['today', 'is', 'a', 'sunny', 'day']

使用limit限定返回的数组大小,如下:

console.log(str.split(' ')) // ['today']
使用正则分隔符(RegExp separator),如下:
console.log(str.split(/\sis\s/)) // ['today', 'a sunny day']
若正则分隔符里包含捕获符号,则括号匹配的结果,将会包含在返回的数组中。
console.log(str.split(/(\s*is\s)/)) //['today', ' is ', 'a sunny day']

String.substr: 返回字符串指定位置开始的指定数量的字符。

语法:str.substr(start[,length])
start表示开始截取字符的位置,可取正值或者负值。取正值时,表示start位置的索引,取负值时表示length + start位置的索引。
length表示截取的字符长度。

javascript复制代码let str = "Yesterday is history. Tomorrow is mystery. But today is a gift.";
console.log(str.substr(47) // today is a gift
console.log(str.substr(-16)) // today is a gift

目前IE不支持start参数取负的索引,如需在IE下支持,请参考Polyfill。

String.substring: 返回字符串两个索引之间的子串。

语法:str.substring(indexA[,indexB])

indexA、indexB表示字符串索引,其中indexB可选,如果省略,则表示返回从indexA到字符串末尾的子串。

描述:substring截取的是从idnexA到indexB(不包含)之间的字符,符合以下规律:

  • 若 indexA == indexB, 则返回一个空字符串;
  • 若省略indexB, 则提取字符串一直到字符串末尾;
  • 若任一参数小于0 或 NaN,则被当做0;
  • 若任一参数大于length,则被当做length;

而如果indexA > indexB,则substring的执行效果就像是两个承诺书调换一般。比如:str.substring(0,1) == str.substring(1, 0)

sql复制代码let str = 'Get outside every day. Miracles are waiting everywhere.'
console.log(str.substring(1,1)) // ''
console.log(str.substring(0)) // Get outside every day. Miracles are waiting everywhere.
console.log(str.substring(-1)) // Get outside every day. Miracles are waiting everywhere.
console.log(str.substring(0, 100)) //Get outside every day. Miracles are waiting everywhere.
console.log(22, NaN)

String.toLocaleLowerCase/ String.tolocaleUpperCase: 返回调用该方法的字符串小写或者大写值,转换规则根本本地话的大小写映射。

语法:str.toLocaleLowerCase()/toLocaleUpperCase()

arduino复制代码console.log('ABCDEFG'.toLocaleLowerCase()); // abcdefg
console.log('abcdefg'.toLocaleUpperCase()); // ABCDEFG

string.toLowerCase/toUpperCase: 将字符串转换为相应的大小写,大写形式,并返回。如下:

arduino复制代码> console.log('ABCDEFG'.toLowerCase()); // abcdefg
console.log('abcdefg'.toUpperCase()); // ABCDEFG

toString/valueOf: 返回字符串本身

语法:str.toString()/str.valueOf()

vbscript复制代码var str = "abc";
console.log(str.toString()); // abc
console.log(str.toString()==str.valueOf()); // true

对于对象而言,toString和valueOf也是非常相似的,他们之间有这细微的差别,如下:

javascript复制代码var x = {
    toString: function() { return 'test' },
    valueOf: function() { return 123}
}

console.log(x) // test
console.log('x=' + x) // x=123
console.log(x+ '=x') // 123=x
console.log(x+ '1') // 1231
console.log(x + 1) // 124
console.log(['x=',x].join('')) // x=test

当"+"操作符一边为数字时,对象x趋向于转换为数字,表达式会优先调用valueOf方法,如果调用数组的join方法,对象x趋向于转换为字符串,表达式会优先调用toString方法。

String.trim: 清除字符串首尾两端的空白并返回。

语法:str.trim()

console.log(' a b c '.trim()) // 'a b c'
trim()方法是ES5.1标准加入的,它不支持IE9一下的低版本浏览器,如需支持,参考:

javascript复制代码if (!String.prototype.trim) {
    String.prototype.trim = function() {
        return this.replace(/^\s+|\s+$/g, '')
    }
}

String.codePointAt(): 返回使用UTF-16编码的给定位置的值的非负整数。

语法:str.codePointAt(position)

arduino复制代码console.log("a".codePointAt(0)); // 97
console.log("\u4f60\u597d".codePointAt(0)); // 20320

String.includes():ES6新增,用来判断一个字符串是否属于另一个字符串。若是,true;若否,false。

语法:str.includes(subString[,position])

subString表示要搜索的字符串,position表示从当前字符串的哪个位置开始搜索字符串,默认值为0.

javascript复制代码var str = "Practice makes perfect.";
console.log(str.includes("perfect")); // true
console.log(str.includes("perfect",100)); // false

实际上,Firefox18~39中该方法名称为contains,由于bug1102219的存在,它被重命名为includes()。目前IE9及一下版本不支持,如需在其它版本浏览器中使用该方法,请参考Polyfill: developer.mozilla.org/zh-CN/docs/…

String.endsWith(ES6): 它基本于contains()功能相同,不同的是,它用来判断一个字符串是否是原字符串的结尾。若是则返回true,否则返回false。

语法:str.endsWith(substring[, position])

与contains方法不同,position参数的默认值为字符串长度。

javascript复制代码var str = "Learn and live.";
console.log(str.endsWith("live.")); // true
console.log(str.endsWith("Learn",5)); // true

目前为止,只有IE9不支持,详情参见:developer.mozilla.org/zh-CN/docs/…

String.normalize(ES6): 按照指定的Unicode正规形式将原字符串正规化。

语法:str.normalize([form])

form参数可省略,目前有四种Unicode正规形式,即 'NFC'、'NFD'、'NFKC'以及'NFKD',form的默认值为'NFC'。如果form传入了非法的参数值,则会跑出RangeError错误。

javascript复制代码var str = "\u4f60\u597d";
console.log(str.normalize()); // 你好
console.log(str.normalize("NFC")); // 你好
console.log(str.normalize("NFD")); // 你好
console.log(str.normalize("NFKC")); // 你好
console.log(str.normalize("NFKD")); // 你好

目前为止,只有IE9不支持。详情参见Polyfill。

String.repeat(es6): 返回重复原字符串多次的新字符串。

语法:str.repeat(count)

count只能取大于等于0的数字,若数字不为整数,将自动转换为整数形式,若为负数或其他值将报错。

less复制代码var str = "A still tongue makes a wise head.";
console.log(str.repeat(0)); // ""
console.log(str.repeat(1)); // A still tongue makes a wise head.
console.log(str.repeat(1.5)); // A still tongue makes a wise head.
console.log(str.repeat(-1)); // RangeError:Invalid count value

目前为止,只有IE9不支持。详情参见Polyfill。

String.startsWith: 判断当前字符串是否是以给定的字符串开始的,若是,则true;若否,则false;

语法:str.startsWith(subString[,position])

less复制代码var str = "Where there is a will, there is a way.";
console.log(str.startsWith("Where")); // true
console.log(str.startsWith("there",6)); // true

HTML有关的方法:

常用的方法有anchor,link其它方法如big、blink、bold、fixed、fontcolor、italics、small、sub、sup均已废除。
现只介绍anchor和link两个方法。

anchor: anchor() 创建一个锚标签。

语法:str.anchor(name)

name指定被创建的a标签的name属性,使用该方法创建的锚点,将会成为document.anchors数组的元素。

ini复制代码var str = "this is a anchor tag";
document.body.innerHTML = document.body.innerHTML + str.anchor("anchor1"); // body末尾将会追加这些内容 <a name="anchor1">this is a anchor tag</a>

link: 创建一个a标签。

语法:str.link(url)

url指定被创建的a标签的href属性,如果URL中包含特殊字符,将自动进行编码。例如''会被转义成&\quot。使用该方法创建的a标签,将会成为document.links数组中的元素。

ini复制代码var str = "百度";
document.write(str.link("https://www.baidu.com")); // <a href="https://www.baidu.com">百度</a>

小结

部分字符串方法之间存在很大的相似性,要主要区分他们的功能和使用场景。如:

  • substr和substring,都是两个参数,作用基本相同,两者第一个参数含义相同,但用法不同,前者可为负数,后者值为负数或者非整数时将隐式转换为0。前者第二个参数表示截取字符串长度,后者第二个参数表示截取字符串的下标;同时substring第一个参数大于第二个参数时,执行结果同位置调换后的结果。
  • serach方法与indexOf方法作用基本一致,都是查询到了就返回子串第一次出现的下标,否则返回-1,唯一的区别就在于search默认将子串转化为正则表达式,而indexOf不做此处理,也不能处理正则。
  • 另外,concat方法由于效率问题,不推荐使用。
  • 通常,字符串中,常用的方法就charAt indexOf lastIndexOf match replace serach slice split substr substring toLowerCase toUpperCase trim valueof等这些。熟悉他们的语法规则就能熟练地驾驭字符串。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值