技术分享之字符串(es5和es6的对比)

2015年发布了javascript的新规范es6,相比于之前的es5变动很大,这就需要我们花费一些时间去学习并使用。
字符串作为一种基本数据类型,在讲解它之前,我们来看一下数据类型方面es6相对于es5有哪些变化?
首先我们看一下es5的数据类型:

es5包括两种数据类型 1.基本数据类型 2.引用数据类型
基本数据类型:String(字符串) Number(数字) Boolean(布尔) null undefined
引用数据类型:Array(数组) object(对象) date(日期)等
es6又增加了哪些呢?
es6新增了一种基本数据类型 **Symbol类型(symbol汉语意思:符号; 象征; 标志; 记号;)**它是一种类字符串类型(这个symbol下次分享的时候会讲到这一块)

let s = Symbol();
typeof s
// "symbol"

好了,未正式开始讲字符串之前讲了这么多,主要想告诉大家 字符串是一种基本数据类型,es6新增了一种新的基本数据类型symbol。

言归正传,字符串讲解正式开始了。
字符串作为常用的一种基本数据类型,在js中占据着很重要的位置。接下来我们来看一下es5中常用的一些方法以及es6中新增的一些方法(当然重点是es6中新增的方法,加上es5主要是为了温故而知新,便于对比记忆)。

(1) es5中常用的方法 之 indexOf() / lastIndexOf()
indexOf(str[,start])
返回 str 在字符串中首次出现的位置,从 start 位置开始查找,如果不存在,则返回 -1。(大部分时候我们都是用来判断一个字符串中是否包含另外一个字符或字符串)

    let a = "string is very userful";
    if(a.indexOf('string') > -1){
        console.log(123456);
    }

    let a = "string is very userful";
    if(a.indexOf('string') != -1){
        console.log(123);
    }
    //  123
    
    let a = "string is very userful";
    if(a.indexOf('string',10) != -1){
        console.log(123456);
    }else{
       console.log(456);
    }
   // 456

lastIndexOf(searchString,startIndex); 从由往左找子字符串,找不到时返回-1. 具体用法同indexOf()类似。
上面的两种方法是根据字符串首次出现的位置来判断字符串是否包含另外一个字符串。(是一种迂回的实现方法)
那么既然是判断字符串中是否包含另外一个字符,有没有直接实现的呢?
有,es6中就增加了这种判断方法includes()

es6新增方法之includes()
includes():返回布尔值,表示是否找到了参数字符串

let s = 'Hello world!';

s.includes('o') // true
s.includes('Hello', 6) // false

这个方法支持第二个参数,表示开始搜索的位置。
同时es6又新增了startsWith(),和endsWith()
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

let s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

这两个方法都支持第二个参数,表示开始搜索的位置。

let s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
以后判断一个字符串中是否包含另外一个字符串时,大家可以使用includes(),这个方法更简洁一些。

(2)es5中有indexOf()这样获取字符位置的方法,也有根据位置获取字符的方法
es5之charAt()和charCodeAt(n)
str.charAt(n)
str.charCodeAt(n)
=> 返回字符串的第 n 个字符,如果不在 0~str.length-1之间,则返回一个空字符串。

扫描二维码关注公众号,回复: 4773826 查看本文章
var str = "javascript";
str.charAt(2); //'v'
str.charAt(12); //''

str.charAt(n)中的n如果是汉字呢?会返回什么样的结果呢?

var s = "吉";

s.length // 2
s.charAt(0) // ''
s.charAt(1) // ''
 s.charCodeAt(0) // 55362
s.charCodeAt(1) // 57271

可以看到charAt返回的是空字符串,charCodeAt返回的是编码值,为此es6新增了方法之codePointAt()
es6新增方法之codePointAt()

JavaScript 内部,字符以 UTF-16 的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符(Unicode 码点大于0xFFFF的字符),JavaScript 会认为它们是两个字符。

var s = "吉";
s.length // 2
s.charAt(0) // ''
s.charAt(1) // ''
s.charCodeAt(0) // 55362
s.charCodeAt(1) // 57271

上面代码中,汉字“吉”(注意,这个字不是“吉祥”的“吉”)的码点是0x20BB7,UTF-16 编码为0xD842 0xDFB7(十进制为55362 57271),需要4个字节储存。对于这种4个字节的字符,JavaScript 不能正确处理,字符串长度会误判为2,而且charAt方法无法读取整个字符,charCodeAt方法只能分别返回前两个字节和后两个字节的值。

ES6 提供了codePointAt方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点。

let s = '?a';

s.codePointAt(0) // 134071
s.codePointAt(1) // 57271
s.codePointAt(2) // 97

s.length; // 3
s.charCodeAt(0); // 55362
s.charCodeAt(1); // 57271
s.charCodeAt(2); // 97

codePointAt方法的参数,是字符在字符串中的位置(从 0 开始)。上面代码中,JavaScript 将“a”视为三个字符,codePointAt 方法在第一个字符上,正确地识别了“吉”,返回了它的十进制码点 134071(即十六进制的20BB7)。在第二个字符(即“吉”的后两个字节)和第三个字符“a”上,codePointAt方法的结果与charCodeAt方法相同。

(3) es6新增之字符串的遍历器接口

ES6 为字符串添加了遍历器接口(详见es6入门这本书的《Iterator》一章),使得字符串可以被for…of循环遍历。

for (let i of 'foo') {
  console.log(i)
}
// "f"
// "o"
// "o"

说白了是可以直接返回key value中的value值
那么用for in 来遍历呢

for (let i of 'foo') {
      console.log(i)
    }
    // 0
    // 1
    // 2
for in得到的是key value中的key值    

其实for of适合遍历数组,for in适合遍历对象
具体for of和for in都有哪些优势和区别,大家如果有兴趣可以看一下张鑫旭写的这篇文章 文章链接

(4) es6新增之字符串的normalize()

许多欧洲语言有语调符号和重音符号。为了表示它们,Unicode 提供了两种方法。一种是直接提供带重音符号的字符,比如Ǒ(\u01D1)。另一种是提供合成符号(combining character),即原字符与重音符号的合成,两个字符合成一个字符,比如O(\u004F)和ˇ(\u030C)合成Ǒ(\u004F\u030C)。

这两种表示方法,在视觉和语义上都等价,但是 JavaScript 不能识别。

'\u01D1'==='\u004F\u030C' //false

'\u01D1'.length // 1
'\u004F\u030C'.length // 2

上面代码表示,JavaScript 将合成字符视为两个字符,导致两种表示方法不相等。

ES6 提供字符串实例的normalize()方法,用来将字符的不同表示方法统一为同样的形式,这称为 Unicode 正规化。

'\u01D1'.normalize() === '\u004F\u030C'.normalize()
// true

(5) es6新增之字符串的repeat()
repeat 英[rɪˈpi:t]
美[rɪˈpit]
vt. 重复; 复述,背诵;
vi. 重做; 重复投票;
n. 重复; (节目) 重演; 重复的事物;

repeat方法返回一个新字符串,表示将原字符串重复n次。

'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""

参数如果是小数,会被取整。

'na'.repeat(2.9) // "nana"

如果repeat的参数是负数或者Infinity,会报错。

'na'.repeat(Infinity)
// RangeError
'na'.repeat(-1)
// RangeError

但是,如果参数是 0 到-1 之间的小数,则等同于 0,这是因为会先进行取整运算。0 到-1 之间的小数,取整以后等于-0,repeat视同为 0。

'na'.repeat(-0.9) // ""

参数NaN等同于 0。

'na'.repeat(NaN) // ""

如果repeat的参数是字符串,则会先转换成数字。

'na'.repeat('na') // ""
'na'.repeat('3') // "nanana"

那么用es5中的方法怎么实现呢?

function repeat(str,num){
    if(num < 1){
    return
    }
    let string = '';
    for(let i = 0; i < num; i++){
      string  = string + str;
    }
    return string;
}

对比来看es6中一个repeat()就可以实现es5中的repeat()函数,而且兼容数据类型更强。
在项目中有哪些使用的场景?这个我还没有想到,希望大家能给我说说。

(6) es6新增之字符串的padStart()和padEnd()
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

猜你喜欢

转载自blog.csdn.net/xiaolinlife/article/details/82748247