JS中文本,就是字符串。
JS使用Unicode 字符集的UTF-16编码。
UTF-16 是一种变长字符编码, 这种编码方式比较特殊, 它将字符编码成 2 字节 或者 4 字节。通常中文占2个字节,可能会占4个字节,例如“”。(1字节表示8位二进制)
UTF-8 是一种变长字符编码,被定义为将码点编码为 1 至 4 个字节,具体取决于码点数值中有效二进制位的数量。通常中文占3个字节,可能会占4个字节。
1、UTF-8和UTF-16都兼容。ASCII码在UTF-8中占用一个字节,在UTF-16中占2个字节。
2、UTF-8和UTF-16编码都是16进制,Unicode也是16进制编码(也称为码点)。
3、不管是UTF-8还是UTF-16都是由Unicode根据各自规则转换而来,Unicode编码都是一致的,只是转换规则不同而已。
4、在 ES6中,字符串是可迭代的,如果对字符串使用 for/of 循环或 …操作符迭代的是字符而不是16位值
let str = "Hello, World!";
let charArray = [...str];
console.log(charArray); // 输出:[ 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' ]
5、JavaScript的字符串操作方法一般操作的是16位值(转换为二进制值),而不是字符。换句话说,它们不会特殊对待代理对,不对字符串进行归一化,甚至不保证字符串是格式正确的UTF-16。
var str = "你"; // 包含中文字符的字符串
var index = str.indexOf("你"); // 查找字符串中第一个出现"你"的位置
console.log(index); // 输出:2,因为‘’占两个字节
6、关于UTF-8和UTF-16详细链接:https://blog.csdn.net/leeta521/article/details/119378886
Unicode编码转换,也可逆向转换☟:
JS字符串放在'' 、""、``
中。
1、他们可以互相包容
2、注意反斜杠\
转义的使用。
3、JS和HTML可以互相混合,HTML使用''和""
来定界字符串。如果要将JS和HTML代码混合在一起,最好JS和HTML分别使用不同的引号。
// 写在一行但表示两行的字符串
'two\nlines'
// 写在三行但只有一行的字符串,注意 \ 后不能有空格,否则会报错
"one\
long\
line"
// 写在两行实际也是两行的字符串
`ab
cd`
// `` '' ""互相包容
`"She said 'hi.'", he said`
// JS和HTML混写
<button onclick="alert('thank you')">点我</button>
JS转义就是反斜杠\
后边跟一个字符串,此时该字符串表示意义就变了。
转义序列:
如果字符\
位于上表之外的字符前面,则这个反斜杠\
会被忽略。eg:\#等同于#
(将来可能会定义新的转义,例如前边讲的ES5允许\
放在换行符前面从而将一个字符串字面量拆成多行)
表中最后3个转义通用:
1、\xnn
只能转义一个字节的ASCII字符(0-127)以及ASCII扩展字符(128-255),范围从00到FF。
eg:console.log('\xA9');//©
2、\unnnn
可以转义0到FFFF之间的Unicode字符。
eg:console.log('\u4E2D');//中;console.log('\u00A9');//©;
3、\u{n}
可以转义所有Unicode字符(0-10FFFF)。
eg:console.log('\u{1F600}');//
1、+
使用
console.log("hello,"+"world!"); // hello,world!
2、比较
===、!==、>、>=、<、<=
比较的是字符串16位值。
字符串长度,也是16位值的长度。
// 外观一样的字符,不一定相等,16位码不一样
let char1 = '\u00C5'; // Å, 这是一个单一的Unicode字符,表示大写的瑞典字母Å
let char2 = '\u0041\u030A'; // A + ̊, 这是两个Unicode字符的组合,第一个是大写字母A,第二个是 Combining Ring Above 字符
console.log(char1); // 输出:Å
console.log(char2); // 输出:Å
console.log(char1 === char2); //false
// js中length,2个字节算一个长度,即一个16位值算一个长度。
console.log('中'.length);//3,‘中’占2个字节,‘’占4个字节
console.log(''.length);//2
3、字符串访问及其API
JS 中的字符串是不可修改的。像 replace()和 toupperCase()这样的方法都返回新字符串,它们并不会修改调用它们的字符串。
字符串也可以被当成只读数组。
更多详情可以查看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String
const str = "";
str[0] = '测';//修改无效,字符串不可修改
console.log(str[0]); // 输出乱码,因为‘’占两个字节,返回的不是有效的 Unicode 字符
console.log(String.fromCodePoint(str.codePointAt(0))); // ""
console.log([...str][0]); // "",转换成数组再获取
const s = 'abc';
console.log(s.charAt(0)); // a
// 归一化。String 的 normalize() 方法返回该字符串的 Unicode 标准化形式。
// 外观一样的字符,但实际上Unicode编码不一样,转换成一致。
const name1 = '\u0041\u006d\u00e9\u006c\u0069\u0065';
const name2 = '\u0041\u006d\u0065\u0301\u006c\u0069\u0065';
console.log(`${name1}, ${name2}`);// Expected output: "Amélie, Amélie"
console.log(name1 === name2);// Expected output: false
console.log(name1.length === name2.length);// Expected output: false
const name1NFC = name1.normalize('NFC');
const name2NFC = name2.normalize('NFC');
console.log(`${name1NFC}, ${name2NFC}`);// Expected output: "Amélie, Amélie"
console.log(name1NFC === name2NFC);// Expected output: true
console.log(name1NFC.length === name2NFC.length);// Expected output: true
``
ES6新增字符串字面量可以用反引号``
来定界。
模板字面量是用反引号(`)分隔的字面量,允许多行字符串、带嵌入表达式的字符串插值和一种叫带标签的模板的特殊结构。
更多模板字面量用法参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Template_literals
//美元符号 $ 也可以被转义,来阻止插值。
`\${1}` === "${1}"; // true
// es6之前使用+来插入变量值
const a = 5;
const b = 10;
console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + ".");
// "Fifteen is 15 and
// not 20."
// es6之后可以用模板字面量插如变量值
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."
标签化模板字面量String.raw()
String.raw() 静态方法是模板字符串的标签函数。它用于获取模板字符串的原始字符串形式,替换表达式(例如 ${foo})会被替换处理,但转义序列(例如 \n)不会被处理。
参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/raw
String.raw`Hi\n${2 + 3}!`;
// 'Hi\\n5!','Hi' 后面的字符不是换行符,'\' 和 'n' 是两个不同的字符。
String.raw`Hi\u000A!`;
// 'Hi\\u000A!',同上,这里得到的会是 \、u、0、0、0、A,6 个字符。
// 任何类型的转义形式都会失效,保留原样输出。
// 你可以通过检查 string 的 .length 属性来确认这一点。
const name = "Bob";
String.raw`Hi\n${name}!`;
// 'Hi\\nBob!',转义序列不会被处理。
String.raw`Hi \${name}!`;
// 'Hi \\${name}!',\$是转移序列,这里不会被处理成表达式,没有插值。
// String.raw()本质上是一个正常的函数,只是专用于模板字符串的标签函数。如果写成正常函数的形式,它的第一个参数,应该是一个具有raw属性的对象,且raw属性的值应该是一个数组,对应模板字符串解析后的值。
// `foo${2 + 2}bar`
// 等同于
String.raw({ raw: ['foo', 'bar'] }, 2 + 2) // "foo4bar"
// test字符串被当做['t', 'e', 's', 't']
String.raw({ raw: "test" }, 0, 1, 2); // 't0e1s2t'
// 作为函数基本实现如下
String.raw = function (strings, ...values) {
let output = '';
let index;
for (index = 0; index < values.length; index++) {
output += strings.raw[index] + values[index];
}
output += strings.raw[index]
return output;
}
后续会有详细讲解,这里只举例代码。
参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_expressions
// 示例文本
const text = 'testing: 1, 2, 3';
// 匹配一个或多个数字
const pattern = /\d+/g;
// 检查是否有匹配项存在
console.log(pattern.test(text)); // => true
// 获取第一个匹配项位置
console.log(text.search(pattern)); // => 9
// 获取所有匹配项组成数组
console.log(text.match(pattern)); // => ['1', '2', '3']
// 将所有匹配项替换为特定字符#
console.log(text.replace(pattern, '#')); // => "testing#: #, #, #
// 基于非数字字符分割文本
console.log(text.split(/\D+/)); // => ["", "1", "2", "3"]