3、Js权威指南第七版读书笔记-第三章 类型、值和变量(中:文本)

三、文本

3.1 概念

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编码转换,也可逆向转换☟:

根据规则转换
16进制转换
UTF-8规则转换
16进制转换
Unicode编码
二进制编码
UTF-8或UTF-16进制编码
'中'Unicode编码0x4E2D
11100100 10111000 10101101
UTF-8编码0xE4B8AD

3.2 字符串字面量

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>

3.3字符串中的转义序列

JS转义就是反斜杠\后边跟一个字符串,此时该字符串表示意义就变了。
转义序列:
3、Js权威指南第七版读书笔记-第三章 类型、值和变量(中:文本)_第1张图片
如果字符\位于上表之外的字符前面,则这个反斜杠\会被忽略。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}');//

3.4使用字符串

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

3.5 模板字面量``

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;
}

3.6 匹配模式(正则)

后续会有详细讲解,这里只举例代码。
参考: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"]

你可能感兴趣的:(#,javascript,ecmascript)