字符串和字符串对象

1.写法

1.普通表示

字符串可以使用单引号或者双引号。多数JS项目约定使用单引号(')。

可以用单引号包含双引号,也可以用双引号包含单引号。

'ab"c"dd'或者"abc'd'e"

如果想单引号包含单引号,或者双引号包含双引号,需要使用转义符号:

'abc\'de' // abc'de
"abc\"de" // abc"de

2. 长字符串

如果想写长字符串,不能直接换行,会报错,有2种常见写法。

var str = "Hello world, I'm Lyra";
// 如果想分行写
// 1)在最后加\
var str = "Hello world,\
I'm Lyra";
// 2) 使用+拼接字符

3. 模版字符串

如果想保留书写格式,使用模版字符串。

var str = `a
b`

1.模板编译

用js实现html模板。

将模版字符串转为正式的模板,以下是ejs模板示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ejs模版解析</title>
</head>
<body>
    <div id="root"></div>
    <script>
        var data = {
            supplies: ['boom', 'cleaner', 'mop']
        }
        var template = `
            <ul>
                <% for(let i=0; i<data.supplies.length;i++) {%>
                    <li><%=data.supplies[i]%></li>
                <%}%>
            </ul>
        `;
        /*
            中间形式代码:
            echo(<ul>);
            for(let i=0; i<data.supplies.length;i++) {
                echo(<li>)
                echo(data.supplies[i])
                echo(</li>)
            }
            echo(</ul>);
        */
        // 写一个编译函数
        function compile(template) {
            // 使用正则表达式解析模板符号,将其转为上面中间形式代码
            regExp = /<%([\s\S]+?)%>/g;
            regExpEqul = /<%=(.+?)%>/g; // 先执行这个替换,否则会错乱
            var template = template
            .replace(regExpEqul, '`); \n  echo( $1 ); \n echo(`')
            .replace(regExp, '`); $1 \n echo(`')
            var template = 'echo(`' + template + '`)';
            // 定义html输出函数
            var output = "";
            function echo(html) {
                output += html;
            }
            // 返回一个可以传入数据的函数
            return function parse(data) {
                eval(template);
                return output;
            }
        }
        const innerHtml = compile(template)(data)
        window.root.innerHTML = innerHtml;
    </script>
</body>
</html>
ejs模板解析

2. 模板标签

非小括号的函数调用方式;使用模版字符串调用。

let message = SaferHTML`<p>${sender} has sent you a message.</p>`;
// SaferHTML 是个标签函数

实际传参形式如下

let message = SafeHTML( ["<p>", " has sent you a message.</p>", raw: Array(2)], ${sender})

可以用来过滤Html字符串,防恶意输入

let message =
  SaferHTML`<p>${sender} has sent you a message.</p>`;

function SaferHTML(templateData) {
  let s = templateData[0];
  for (let i = 1; i < arguments.length; i++) {
    let arg = String(arguments[i]);

    // Escape special characters in the substitution.
    s += arg.replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");

    // Don't escape special characters in the template.
    s += templateData[i];
  }
  return s;
}
过滤Html字符串

2.字符的Unicode码表示

1)\HHH 三位8进制数      // 只能表示256个字符

2)\xHH  两位16进制数   // 只能表示256个字符

3)\uHHHH 四位16进制数  

4) \u{字符}      // 大括号内的数字是16进制的数字,即使没有0x符号。 ES6表示法,可以展示大于0xFFFF的值

// 示例:版权符号
'\251' // ©️
'\xA9' // ©️
'\u00A9' // ©️

s引擎内部每个字符都是utf-16格式,16位存储(2个字节)。

但是在ES5中,对于超过\u0000-\uFFFF范围的字符来说,js会将其分成两个字符(4个字节)。str.length的长度为2。

在ES6中,可以使用大括号来表示码点大于0xFFFF的字符,如:

'\u1D306'  // 在ES5中因为超过\uFFFF,会被解析成"\u1D30" + 6, 即"ᴰ6"
// ES5如果想要正确显示大于0xFFFF的字符,需要将其写成第一个字符\uD800-\uDBFF之间,第二个字符位于\uDC00-\uDFFF之间的拼接字符。
'\uD834\uDF06' // "𝌆"--正确

// ES6中就可以直接用大括号表示
'\u{1D306}' //"𝌆"
 

码点大于0xFFFF的字符,可以被for...of...遍历器正确遍历

3.转义字符

需要使用反斜杠转义的主要有:

\r 回车
\n 换行
\\ 反斜杆
\' 单引号
\" 双引号

4. Base64编码

Base64,顾名思义,就是基于64个字符。就是将任意值转为0-9,A-Z,a-z,+,/这64个字符组成的可打印字符。

用途:1)显示特殊字符,比如ASCII码的前31位。2)将二进制数据(比如图片)转为文本

有两个方法:

btoa(str); // 转为Base64
atob(str); // 从Base64转为原来的值

上面的方法仅适用于ASCII码,对于诸如汉字等非ASCII码,需要先通过encodeURIComponent处理

var str ="你好";
btoa(encodeURIComponent(str)); //"JUU0JUJEJUEwJUU1JUE1JUJE"
decodeURIComponent(atob("JUU0JUJEJUEwJUU1JUE1JUJE")) // "你好"

 5.字符串对象方法

1.静态方法--返回码点对应字符

1) String.fromCharCode(码点,码点,,,) 

返回码点对应的字符,使用于0x0000-0xFFFF之间的字符,超出的可以拆分成两个字符

2) String.fromCodePoint(码点,,,)

作用同上,但是作为ES6新增方法,可以解析大于0xFFFF的字符。

String.fromCodePoint(0x20bb7);  // "𠮷"

3)String.raw`str`---标签函数

将模版字符串的所有变量替换,并且将斜杠转义

String.raw`Hi\n${2+3}!` === "Hi\\n5!"; // true
// 但是在页面上展示是"Hi\n5!"
// 相当于
String.raw({raw: ['Hi\\n','!'],},5);

2. 实例方法--基本方法

1)String.prototype.charAt([index]) ---根据位置返回字符(0x0000-0xFFFF)

index可以省略,默认是0,即第一个位置。

和字符串按照数组索引取值类似,不同点在于[]取值超过范围返回undefined,

该方法超过有效index,返回“”空字符串。

2) String.prototype.charCodeAt([index]) --- 根据位置返回码点(十进制)(0x0000-0xFFFF)

index默认是0,结果想转16进制,可以调用toString(16)

3) String.prototype.codePointAt([index]) --- 根据位置返回码点(十进制)

功能和2)相同,但是可以识别大于0xFFFF的字符。

'ad'.codePointAt(1); // 100

4)String.prototype.normalize()---Unicode码统一化

返回结果相同的不同表示形式统一化

有四种参数: NFC,NFD,NFKC,NFKD

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

3.实例方法---字符串变更

1) String.prototype.concat(多个参数) ---拼接字符串

会将不是字符串的参数转为字符串

2)String.prototype.slice(start, end) ---截取字符串

遵循[)左闭右开原则,如果参数<0,表示从后面数。

如果start>end,返回“”

3)String.prototype.substring(start, end) --- 截取字符串

遵循[)左闭右开原则,如果参数<0, 将负数转为0.

如果start>end,交换两者的值。

4)String.prototype.substr(start,length) --- 截取字符串

如果start<0, 从后面数;

如果length<0, 将length置为0

5)String.prototype.toLowerCase(),String.prototype.toUpperCase()--转大小写

6)String.prototype.split(string/RegExp[, limit]) --- 分割字符串

第一个参数可以是字符串或者正则表达式,第二个限制返回的长度。

如果正则表达式带有括号,则括号匹配的内容也会返回

'aaa*a*'.split(/a*/);
// ['', '*', '*']
'aaa*a*'.split(/(a*)/);
// ['', 'aaa' , '*', 'a', '*']

7)String.prototype.replace(string/RegExp, string/function)---替换字符串

不改变原字符串。

一般只替换第一个匹配的字符

'abaaaaaac'.replace('a', 'A'); //"Abaaaaaac"

当正则表达式使用g修饰符时,会替换所有匹配的字符

'abaaaaaac'.replace(/a/g, 'A') //"AbAAAAAAc"

第二个参数如果是字符串,可以有几个特殊值。

1) '$&' // 被替换的字符
'abc'.replace(/b/, '$&'); // abc 
2)'$`' // 被替换内容前面的所有字符
'dddabc'.replace(/b/, '$`'); //"dddadddac"
3) '$\'' // 被替换内容后面的所有字符
'abcd'.replace(/b/, '$\''); //acdcd
4) '$n' // 组匹配的第n个内容
'abc'.replace(/(.)(.)/g, '$&-$1-$2-$`-$\'-$$'); // "ab-a-b--c-$c"
//由上可知,$&==ab,$1 == a,$2==b,$` == '', $\' === c
5)$$ // 表示$符号
6)$<组名> // 表示具名组匹配的引用;和$n性质一样

第二个参数如果是函数,函数参数为:($&, $1,.,,...$n, $&索引, 原字符串,groups)

8)String.prototype.repeat(n)---将字符串重复n次

如果n是Infinity或者<=-1, 返回RangeError;

如果-1<n<1, n默认取0;

如果是其他值,向下取整

9) String.prototype.trim()----去除首尾空白字符 ES5

String.prototype.trimStart()--- 去除首部空白字符ES2019

String.prototype.trimEnd() --- 去除尾部空白字符ES2019

10)padStart(length, str),padEnd(length, str) --- 补全字符串

length表示补全后的字符串长度,原字符串长度大于length,返回原值;

str用于补全的字符,默认是空格。

'05'.padStart(10,'YYYY-MM-DD'); // "YYYY-MM-05"

4. 实例方法---字符串查找

1)indexOf(str[, start])---从start向后查找第一个目标字符串的位置

lastIndexOf(str[, start])---从start向前开始查找第一个目标字符串的位置

start表示开始查找的位置

'abcdaddfdsa'.indexOf('a'); // 0
'abcdaddfdsa'.indexOf('a',4); // 4
'abcdaddfdsa'.indexOf('a',-1); // 0 当start<0时,按照0处理
'abcdaddfdsa'.lastIndexOf('a',3); // 0

2) search(str/RegExp) --- 从头查找目标字符串第一个出现的位置

作用和indexOf相同,不同点在于search可以使用正则表达式

'abca'.search('a');  // 0
'abca'.search(/a/);  // 0

3)match(str/RegExp) --- 用数组返回查找的结果

如果查找失败,返回null;

当为正则表达式时,如果有g修饰符,返回所有的匹配结果,忽略组匹配。

当为正则表达式时,如果没有g修饰符,或者为字符串时,会返回组匹配,并且返回input和index属性。

'abca'.match(/(.)/g);  //  ["a", "b", "c", "a"]
'abca'.match(/(.)/); // ["a", "a", index: 0, input: "abca", groups: undefined]  
//其中第一个是匹配结果,第二个是组匹配,index是匹配的位置,input是原字符串

4)matchAll(RegExp) --- 用遍历器返回所有匹配结果。返回的是遍历器。

和3)相比, 可以遍历整个字符串,还可以获得组匹配。

matchAll返回的是一个遍历器;好处是比数组节约资源;

可以通过...扩展运算符和Array.from()可以将其转为数组。

const a = 'abca'.matchAll(/(.)/g); // RegExpStringIterator {}
[...a];
/*
    [
        ["a", "a", index: 0, input: "abca", groups: undefined],
        ["b", "b", index: 0, input: "abca", groups: undefined],
        ["c", "c", index: 0, input: "abca", groups: undefined],
        ["a", "a", index: 0, input: "abca", groups: undefined]    
    ]
*/            

5)includes(str)---通过布尔值返回查找结果

6)startsWith(str, start) --- 通过布尔值是否以str开头

start参数表示查找的起始位置

'abc'.startsWith('a'); // true
'abc'.startsWith('a', 1); // false

7)endsWith(str, beforeIndex)---通过布尔值是否以str结尾

beforeIndex表示前beforeIndex个字符。

'abc'.endsWith('a',1); // true 前一个字符以a结尾
'abc'.endsWith('a'); // false

5. 实例方法-字符串比较

str1.localeCompare(str2) --- 比较字符串大小

按照自然语言比较,不同于比较运算符

结果是1, 表示str1 > str2

结果是0,表示str1 === str2

结果是-1,表示str1 < str2

'B'.localeCompare('a'); // 1 前者大
'B'>'a'// false 前者小

该方法还可以用来比较汉字,按照汉语拼音的顺序

'按'.localeCompare('们') // -1
'我'.localeCompare('们') // 1

 

posted @ 2019-10-03 18:30  Lyra李  阅读(1094)  评论(0编辑  收藏  举报