咱们对字符串类型的数据并不会陌生。let str = 'value'
就是一个最简单的生成字符串例子。javascript
咱们还能够经过String(thing)
和new String(thing)
将任何类型的数据转化成字符串。注意,new String(thing)
会生成一个String
类型的对象将字符串包裹。html
例如,把一个空对象传入,String({})
返回的值为"[object Object]"
,这里不得不提的就是,其余类型默认的toString()方法本质就是调用String({})
。java
字符串量能直接使用String
的属性和方法,如'string'.toLowerCase()
。其实语言内部会将'string'
封装成对象,再执行相应的方法,最后字符串对象使用valueOf()
或toString()
方法获得字符串的值。正则表达式
经常使用属性只有一个:length
,返回字符串的长度。
数据库
如下介绍的,除了String.raw()
为静态方法,其余都是字符串对象的方法。全部的字符串方法都不会对原字符串修改,都是返回一个新的字符串或结果。数组
padString
表示用于填充的字符串,默认为" "
。padString
表示用于填充的字符串,默认为" "
。count
表示重复的次数。position
表示开始查找的索引,默认为 0 。position
表示开始查找的索引,默认为 0 。position
表示开始查找的索引,默认为 0 。fromIndex
表示开始查找的索引。indexOf()
相似,不一样的是,返回给定的字符串在原字符串的最后一次出现的索引值。beginSlice
表示做为开始字符的索引,endSlice
表示结束位置的索引,负数表示从后数起。indexEnd
不能为负数。separator
表示做为分隔符的字符串或正则表达式;limit
表示字符串数组的最大长度。form
默认为 "NFC
"。例子:'\u01D1'.normalize() === '\u004F\u030C'.normalize(); // true
。NaN
。对于都是"基本平面"的字符串,索引值与其所在位置相同;但对于含有"辅助平面"的字符串来讲就要注意,如𝌆
为 4 字节字符,须要两个 UTF-16 代码单元表示,'𝌆a'.charCodeAt(2)
的值为 97 ,而非NaN
,而索引 1 和 2 的值分别为𝌆
的高位和低位的码点数值。charCodeAt()
方法返回的结果一致,除了索引超出范围返回的是undefined
。String
对象内置Iterator
对象,经过属性[Symbol.iterator]
获取,在遍历时调用,如for...of
运算、展开运算符(...
)等。bash
获取迭代器:
函数
let strIterator = 'abcde'[Symbol.iterator]();
console.log(strIterator.next().value); // 'a'
console.log(strIterator.next().value); // 'b'
console.log(strIterator.next().value); // 'c'复制代码
修改迭代器:
测试
// 必须建立字符串对象
let str = new String('abcde');
// 原生迭代器效果
for (let i of str) {
console.log(i);
}
// 打印结果: a b c d e
// 自定义迭代器函数
str[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
}
// 测试自定义迭代器
console.log(...str); // 1 2 3复制代码
字符串模板用"反引号"表示,即 ` `
。ui
模板字符串内,字符串量能够直接写,${ }
内执行JavaScrip
代码。用于生成一个带运算的字符串结果。
let num1 = 123,
num2 = 456;
let temp = `hello ${num1 + num2} world !`;
console.log(temp); // "hello 579 world !"复制代码
咱们通常调用函数的方式是fn(['hello ', 'world'], 999)
,函数名后用括号包裹参数。而标签模板能够这样写:fn`hello ${args}world`
,函数名后直接跟``
。注意,这两种方式的参数是一致的。
分解:
带${ }
的模板字符串,内部实际上是被${
和}
分割成多份。以`hello ${999}world${666} !`
为例:
` hello ${999} world ${666} ! `复制代码
${ }
的外面是字符串直接量,而${ }
之间是 js 代码。如此看来,字符串模板被分红了 5 份,而字符串直接量会组成字符串数组,因此传入函数时是 3 个参数,分别是['hello ', 'world', ' !']
、999
、666
。下面给出简单例子说明。
// 用于查看传参状况的函数
function fn() {
console.log(arguments[0])
}
fn`hello ${999}world${666} !`;
// 下图看结果复制代码
谈到模板字符串,不得不谈String
对象的一个静态方法:String.raw()。通常都是以标签函数的方式调用它,即String.raw``
,固然,你可使用普通函数的()
方式传参,只不过要按照上面额规则手动转化一下。它的用途是获取一个模板字符串的原始字面量值,简单说就是把全部的反斜杠(\
)转义。
String.raw `Hi\u000A!`; // "Hi\\u000A!"
String.raw `Hi\n${999}!`; // "Hi\\n999!"
String.raw`\\`; // "\\\\"
复制代码
code point
(又称码点)来表示一个字符(即该字符在子库表中的位置),这个值称为字符对应于编码字符集(如:Unicode、ASCII)的序号。用商场储物柜为例子。
字符,等于单个柜箱,存放着咱们想看的内容。
整个储物柜就是字库表。
为每一个柜箱按顺序贴上标签后,整个储物柜就是编码字符集,每一个数字(码点)对应一个柜箱(字符)。
咱们手上有一份查询表格,但表格上只能写二进制或十六进制的数字。以什么样的方式把储物柜上的数字对应到表格上(映射),就是字符编码。
ASCII 既是字符集,也是字符编码。用一个字节的长度存储字符。自行百度,很少介绍。
Unicode 是一个字符集,为每一个符号指定一个编号,即"码点"(code point)。其目标是将全世界全部的字符包含在一个集合里,计算机只要支持这一个字符集,就能显示全部的字符。
每一个区能够存放 65536 个(216)字符,称为一个平面(plane)。
目前,一共有 17 个(25)平面,也就是说,整个 Unicode 字符集的大小如今是 221 。
最前面的 65536 个字符位,称为基本平面(缩写 BMP ),它的码点范围是从 0 一直到 216-1 ,写成 16 进制就是从 U+0000 ~ U+FFFF
。
剩下的字符都放在辅助平面(缩写 SMP ),码点范围为 U+010000 ~ U+10FFFF
。
UTF-32 是字符编码方式,用固定长度的 4 字节表示一个字符,与 Unicode 字节内容一一对应码点。例如:
U+597D = 0x0000 597D复制代码
但缺点很明显,浪费空间。HTML5 标准就明文规定,网页不得编码成UTF-32。
UTF-8 是一种变长的编码方法,字符长度从 1 个字节到 4 个字节不等。越是经常使用的字符,字节越短,最前面的 128 个字符,只使用 1 个字节表示,与 ASCII 码彻底相同。如,编码范围在0x0000 - 0x007F
只占用 1 字节,而0x010000 - 0x10FFFF
要占用 4 字节。是最多见的网页编码。
因为 UTF-8 是变长的,若不直到其长度,连续的字符则没法解析。如何判断其长度,这就涉及它的编码规则:
0xxx xxxx
。用阮一峰的博文的图表展现:
Unicode 符号范围 (十六进制) | UTF-8 编码方式 (二进制) | 字节 |
---|---|---|
0000 0000-0000 007F | 0xxxxxxx | 1 |
0000 0080-0000 07FF | 110xxxxx 10xxxxxx | 2 |
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx | 3 |
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 4 |
图表中x
组合而成的就是实际的 Unicode 码点。
UTF-16 编码介于 UTF-32 与 UTF-8 之间,同时结合了定长和变长两种编码方法的特色。编码规则就是,基本平面的字符占用 2 个字节,辅助平面的字符占用 4 个字节。
由于在基本平面内,从U+D800 ~ U+DFFF
是一个空段,空间为 211 ,即 2 个 210 。而一个辅助平面的字符须要的空间为 220 ,恰好能够拆分红两个空段内的字符,高位(H)映射在U+D800 ~ U+DBFF
;低位(L)映射在U+DC00 ~ U+DFFF
。所以解决了 4 字节的字符的识别问题。
因此,对于基本平面,Unicode 与 UTF-16 码相同。
对于辅助平面,Unicode 与 UTF-16 的转化公式以下:
H = Math.floor((c-0x10000) / 0x400) + 0xD800
L = (c - 0x10000) % 0x400 + 0xDC00复制代码
不难理解,辅助平面的码点是从U+10000
开始,则减去0x10000
;上面提到高低位各占 10 位,则除以0x400
获得的商和余数则分别位高低位的起点值,最后高位加上基础值0xD800
,低位加上0xDC00
获得目标值。(内容总结自阮一峰的博文)
JavaScript 语言采用 Unicode 字符集,可是只支持一种编码方法,就是 UCS-2 。因为历史缘由(阮一峰的博文有介绍),UCS-2 只支持 2 字节的字符,4 字节的字符被当成 2 个 2 字节的字符解析。如今已经没有 UCS-2 。
ES6 加强对 Unicode 的支持:
console.log('\ud834\udf06'); // 𝌆
。'𝌆' === '\u{1d306}'; // true
。2 字节的字符能够省略{}
。u
修饰符,对正则表达式添加 4 字节码点的支持。例子:/^.$/.test('𝌆'); // false
,/^.$/u.test('𝌆'); // true
。