背景
const text = "??"; // 占用了兩個(gè)碼元(32位)
console.log("字符串長(zhǎng)度:", text.length); // 字符串長(zhǎng)度: 2
console.log("使用正則測(cè)試:", /^.$/.test(text)); // 使用正則測(cè)試: false
console.log("得到第一個(gè)碼元:",text.charCodeAt(0)); // 得到第一個(gè)碼元: 55362
console.log("得到第二個(gè)碼元:",text.charCodeAt(1)); // 得到第二個(gè)碼元: 57271
console.log("得到第一個(gè)碼點(diǎn):",text.codePointAt(0)); // 得到第一個(gè)碼點(diǎn): 134071
console.log("得到第二個(gè)碼點(diǎn):",text.codePointAt(1)); // 得到第二個(gè)碼點(diǎn): 57271
早期氧腰,由于存儲(chǔ)空間寶貴,Unicode 使用 16位二進(jìn)制 來(lái)存儲(chǔ)文字刨肃。我們將一個(gè) 16位二進(jìn)制編碼 叫做 一個(gè)碼元(Code Unit)古拴。
后來(lái)真友,由于技術(shù)的發(fā)展,Uincode 對(duì)文字編碼進(jìn)行了擴(kuò)展盔然,將某些文字?jǐn)U展到了 32位(占用兩個(gè)碼元)桅打,并且是嗜,將某個(gè)文字對(duì)應(yīng)的 二進(jìn)制數(shù)字叫做碼點(diǎn)(Code Point)。
ES6 為了解決這個(gè)困擾挺尾,為字符串提供了方法:codePointAt 。根據(jù)字符串碼元的位置得到其碼點(diǎn)遭铺。
// 判斷字符串char,是32位甫题,還是16位
function is32bit(char) {
// 如果碼點(diǎn)大于了16位二進(jìn)制的最大值涂召,則其是32位的
return char.codePointAt(0) > 0xffff;
}
console.log(is32bit("??")); // true
console.log(is32bit("a")); // false
得到一個(gè)字符串碼點(diǎn)的真實(shí)長(zhǎng)度:
// 得到一個(gè)字符串碼點(diǎn)的真實(shí)長(zhǎng)度
function getLengthOfCodePoint(str) {
var len = 0;
for(let i = 0; i < str.length; i ++) {
// i 在索引碼元
if(str.codePointAt(i) > 0xffff) {
// 當(dāng)前字符串,在這個(gè)位置芹扭,占用了兩個(gè)碼元
i ++;
}
len ++;
}
return len;
}
console.log(getLengthOfCodePoint("aa??a5")); // 5
- 同時(shí),ES6為正則表達(dá)式添加了一個(gè)flag:u 舱卡。如果添加了該配置队萤,則匹配時(shí)使用碼點(diǎn)匹配。
const text = "??";
console.log("使用正則測(cè)試:", /^.$/u.test(text)); // 使用正則測(cè)試: true
字符串 API
以下均為字符串的實(shí)例(原型)方法要尔。
1. includes : 判斷字符串中是否包含指定的子字符串。
includes(str, index);
第二個(gè)參數(shù)index表示從哪個(gè)位置開(kāi)始查找既绩。
const text = "abc";
console.log(text.includes("c")); // true
console.log(text.includes("f")); // false
console.log(text.includes("a", 0)); // true
console.log(text.includes("b", 0)); // true
console.log(text.includes("b", 2)); // false
2. startsWith : 判斷字符串中是否以指定的字符串開(kāi)始还惠。
startsWith(str, index);
第二個(gè)參數(shù)index表示從哪個(gè)位置開(kāi)始是否是以str開(kāi)頭。
const text = "abc是";
console.log(text.startsWith('a')); // true
console.log(text.startsWith("f")); // false
console.log(text.startsWith('c', 2)); // true
console.log(text.startsWith("c", 1)); // false
3. endsWidth : 判斷字符串中是否以指定的字符串結(jié)尾船殉。
const text = "abc是";
console.log(text.endsWith("a")); // false
console.log(text.endsWith("是")); // true
4. repeat : 將字符串重復(fù)指定的次數(shù)西篓,返回新的字符串笆怠。
const text = "abc是";
console.log(text.repeat(2)); // abc是abc是
console.log(text.repeat(1)); // abc是
正則中的粘連標(biāo)記
標(biāo)記名:y
含義:匹配時(shí)誊爹,完全按照正則對(duì)象中的lastIndex位置開(kāi)始匹配瓢捉,并且匹配的位置必須在lastIndex位置办成。
const text = "hello world";
const reg = /w\w+/y;
reg.lastIndex = 6;
console.log(reg.test(text)); // true
console.log(reg.lastIndex);
模板字符串
ES6之前處理字符串繁瑣的兩個(gè)方面:
- 多行字符串
const demo = "hello \n world"
console.log(demo); // hello
// world
- 字符串拼接
const a = 123;
const demo = "hello "+ a +"world";
console.log(demo); // hello 123world
在ES6中,提供了模板字符串的書(shū)寫(xiě)诈火,可以非常方便換行和拼接,要做的刀崖,僅僅是將字符串的開(kāi)始或結(jié)尾改完 ``符號(hào)拍摇。
const demo = `hello
world`;
console.log(demo); // hello
// world
如果要在字符串中拼接js表達(dá)式亮钦,只需要在模板字符串中使用 ${js表達(dá)式}充活。表達(dá)式可以是任何有意義的數(shù)據(jù),表達(dá)式可以嵌套映穗。
const a = 123;
const demo = `hello ${a} world`;
console.log(demo); // hello 123 world
模板字符串標(biāo)記
實(shí)現(xiàn)方式:
const love1 = "蘋(píng)果";
const love2 = "葡萄";
const demo = myTag`我喜歡吃 ${love1} 幕随,也喜歡吃 ${love2}`;
// 相當(dāng)于:demo = myTag(["我喜歡吃","也喜歡吃",""], "蘋(píng)果", "葡萄")
function myTag(parts) {
console.log(parts); // ["我喜歡吃 ", " 蚁滋,也喜歡吃 ", ""]
console.log(arguments); // 0: (3) ["我喜歡吃 ", " ,也喜歡吃 ", "", raw: Array(3)] 1: "蘋(píng)果" 2: "葡萄"
const values = Array.prototype.slice.apply(arguments).slice(1);
console.log(values); // ["蘋(píng)果", "葡萄"]
// parts.length = values.length + 1;
let str = "";
for(let i = 0; i < values.length; i ++) {
str += parts[i] + "a" + values[i];
if(i === values.length - 1) {
str += parts[i + 1];
}
}
return str;
}
console.log(demo); // 我喜歡吃 a蘋(píng)果 赘淮,也喜歡吃 a葡萄
- String.raw : 標(biāo)記模板字符串全部為普通字符辕录,沒(méi)有特殊或轉(zhuǎn)義字符梢卸。
const demo = String.raw`abc \n abc`;
console.log(demo); // abc \n abc
- safe : 對(duì)危險(xiǎn)內(nèi)容進(jìn)行轉(zhuǎn)義。
未標(biāo)記前:
<p>
<input type="text" id="text">
<button id="btn">設(shè)置div的內(nèi)容</button>
</p>
<div id="container"></div>
const container = document.getElementById("container");
const text = document.getElementById("text");
const btn = document.getElementById("btn");
btn.onclick = function() {
container.innerHTML = `<p>
${text.value}
</p>`
}
標(biāo)記后:
const container = document.getElementById("container");
const text = document.getElementById("text");
const btn = document.getElementById("btn");
btn.onclick = function() {
container.innerHTML = safe`<p>
${text.value}
</p>`
}
function safe(parts) {
const values = Array.prototype.slice.apply(arguments).slice(1);
let str = "";
for(let i = 0; i < values.length; i ++) {
const v = values[i].replace(/</g, "<").replace(/>/g, ">");
str += parts[i] + v;
if(i === values.length - 1) {
str += parts[i + 1];
}
}
return str;
}
總結(jié):
在模板字符串書(shū)寫(xiě)之前蚣旱,可以加上標(biāo)記:
標(biāo)記名`模板字符串`
標(biāo)記是一個(gè)函數(shù)襟齿,函數(shù)參數(shù)如下:
參數(shù)1:被插值分割的字符串?dāng)?shù)組。
后續(xù)參數(shù):所有的插值位隶。