四、JavaScript 字符串
这一章将集中讨论字符串、JavaScript String
对象和String
对象的内置函数。您将学习如何访问、比较、分解和搜索现实生活中常用的字符串。此外,本章将探讨字符串编码、解码、加密和解密。到本章结束时,你将理解如何有效地使用 JavaScript 字符串,并对字符串编码和加密有一个基本的了解。
JavaScript 字符串原语
JavaScript 的原生String
原语带有各种常见的字符串函数。
字符串访问
访问字符时,使用.chartAt()
。
1 'dog'.charAt(1); // returns "o"
.charAt(index)
获取一个索引(从 0 开始)并返回字符串中该索引位置的字符。
对于字符串(多字符)访问,您可以使用.substring(startIndex, endIndex)
,它将返回指定索引之间的字符。
1 'YouTube'.substring(1,2); // returns 'o'
2 YouTube'.substring(3,7); // returns 'tube'
如果您没有传递第二个参数(endIndex
),它将返回从指定的开始位置到结束位置的所有字符值。
1 return 'YouTube'.substring(1); // returns 'outube'
字符串比较
大多数编程语言都有比较字符串的功能。在 JavaScript 中,这可以通过使用小于和大于操作符来实现。
1 var a = 'a';
2 var b = 'b';
3 console.log(a < b); // prints 'true'
这对于在排序算法时比较字符串非常有用,这将在本书后面介绍。
但是,如果您正在比较两个不同长度的字符串,它将从字符串的开头开始比较,直到较小字符串的长度。
1 var a = 'add';
2 var b = 'b';
3
4 console.log(a < b); // prints 'true'
在这个例子中,比较了a
和b
。由于a
小于b
,所以a < b
的计算结果为true
。
1 var a = 'add';
2 var b = 'ab';
3 console.log(a < b); // prints 'false'
在这个例子中,在比较了'a'
和'b'
之后,比较了'd'
和'b'
。处理无法继续,因为'ab'
的一切都已被关注。这和比较'ad'
和'ab'
是一样的。
1 console.log('add'<'ab' == 'ad'<'ab'); // prints 'true'
字符串搜索
要在字符串中查找特定的字符串,可以使用.indexOf(searchValue[, fromIndex])
。这需要一个作为要搜索的字符串的参数,以及一个用于搜索的起始索引的可选参数。它返回匹配字符串的位置,但是如果什么也没有找到,那么返回-1。请注意,该函数区分大小写。
1 'Red Dragon'.indexOf('Red'); // returns 0
2 'Red Dragon'.indexOf('RedScale'); // returns -1
3 'Red Dragon'.indexOf('Dragon', 0); // returns 4
4 'Red Dragon'.indexOf('Dragon', 4); // returns 4
5 'Red Dragon'.indexOf(", 9); // returns 9
要在更大的字符串中检查搜索字符串的出现,只需检查-1 是否从. indexOf 返回。
1 function existsInString (stringValue, search) {
2 return stringValue.indexOf(search) !== -1;
3 }
4 console.log(existsInString('red','r')); // prints 'true';
5 console.log(existsInString('red','b')); // prints 'false';
您可以使用附加参数在字符串中的某个索引后进行搜索。一个例子是计算某些字母的出现次数。在以下示例中,将计算字符'a'
的出现次数:
1 var str = "He's my king from this day until his last day";
2 var count = 0;
3 var pos = str.indexOf('a');
4 while (pos !== -1) {
5 count++;
6 pos = str.indexOf('a', pos + 1);
7 }
8 console.log(count); // prints '3'
最后,如果字符串以指定的输入开始,startsWith
返回 true(布尔值),并且endsWith
检查字符串是否以指定的输入结束。
1 'Red Dragon'.startsWith('Red'); // returns true
2 'Red Dragon'.endsWith('Dragon'); // returns true
3 'Red Dragon'.startsWith('Dragon'); // returns false
4 'Red Dragon'.endsWith('Red'); // returns false
字符串分解
要将一个字符串分解成多个部分,可以使用.split(separator)
,这是一个非常有用的函数。它接受一个参数(分隔符)并创建一个子字符串数组。
1 var test1 = 'chicken,noodle,soup,broth';
2 test1.split(","); // ["chicken", "noodle", "soup", "broth"]
传递一个空分隔符将创建一个包含所有字符的数组。
1 var test1 = 'chicken';
2 test1.split(""); // ["c", "h", "i", "c", "k", "e", "n"]
当一个字符串中列出多个项目时,这很有用。可以将字符串转换成数组,以便轻松地遍历它们。
字符串替换
.replace(string, replaceString)
用另一个字符串替换字符串变量中的指定字符串。
1 "Wizard of Oz".replace("Wizard","Witch"); // "Witch of Oz"
正则表达式
正则表达式( regexes )是定义搜索模式的一组字符。学习如何使用正则表达式本身就是一项艰巨的任务,但是作为一名 JavaScript 开发人员,了解正则表达式的基础知识非常重要。
JavaScript 还带有原生对象RegExp
,用于正则表达式。
RegExp
对象的构造函数有两个参数:正则表达式和可选的匹配设置,如下所示:
i Perform case-insensitive matching
g Perform a global match (find all matches rather than stopping after first match)
m Perform multiline matching
RegExp
有以下两个功能:
-
search()
:测试字符串中的匹配。这将返回匹配的索引。 -
match()
:匹配测试。这将返回所有匹配项。
JavaScript String
对象还有以下两个与 regex 相关的函数,它们接受RegExp
对象作为参数:
-
exec()
:测试字符串中的匹配。这将返回第一个匹配项。 -
test()
:测试字符串中的匹配。这将返回true
或false
。
基本正则表达式
以下是基本的正则表达式规则:
^
:表示字符串/行的开始
\d
:查找任意数字
[abc]
:查找括号之间的任何字符
[^abc]
:查找括号中除以外的任何字符
*[0-9]
:查找括号之间的任意数字
[^0-9]
:查找括号中除以外的任何数字
*(x|y)
:查找任何指定的备选项
以下返回索引 11,它是字符D
的索引,该字符是匹配的正则表达式的第一个字符:
1 var str = "JavaScript DataStructures";
2 var n = str.search(/DataStructures/);
3 console.log(n); // prints '11'
常用的正则表达式
正则表达式对于检查 JavaScript 中用户输入的有效性非常有帮助。一种常见的输入检查是验证它是否有任何数字字符。
以下是开发人员经常使用的五种正则表达式。
任何数字字符
/\d+/
1 var reg = /\d+/;
2 reg.test("123"); // true
3 reg.test("33asd"); // true
4 reg.test("5asdasd"); // true
5 reg.test("asdasd"); // false
仅数字字符
/^\d+$/
1 var reg = /^\d+$/;
2 reg.test("123"); // true
3 reg.test("123a"); // false
4 reg.test("a"); // false
浮动数字字符
/^[0-9]*.[0-9]*[1-9]+$/
1 var reg = /^[0-9]*.[0-9]*[1-9]+$/;
2 reg.test("12"); // false
3 reg.test("12.2"); // true
仅字母数字字符
/[a-zA-Z0-9]/
1 var reg = /[a-zA-Z0-9]/;
2 reg.test("somethingELSE"); // true
3 reg.test("hello"); // true
4 reg.test("112a"); // true
5 reg.test("112"); // true
6 reg.test("^"); // false
查询字符串
/([^?=&]+)(=([^&]*))/
在 web 应用程序中,出于路由或数据库查询的目的,web URLs 经常在 URL 中传递参数。
例如,对于 URL http://your.domain/product.aspx?category=4&product_id=2140&query=lcd+tv
,URL 可能会对后端 SQL 查询做出如下响应:
1 SELECT LCD, TV FROM database WHERE Category = 4 AND Product_id=2140;
要解析这些参数,正则表达式会很有用。
1 var uri = 'http://your.domain/product.aspx?category=4&product_id=2140&query=lcd+tv' ;
2 var queryString = {};
3 uri.replace(
4 new RegExp ("([^?=&]+)(=([^&]*))?" , "g" ),
5 function ($0, $1, $2, $3) { queryString[$1] = $3; }
6 );
7 console.log('ID: ' + queryString['product_id' ]); // ID: 2140
8 console.log('Name: ' + queryString['product_name' ]); // Name: undefined
9 console.log('Category: ' + queryString['category' ]); // Category: 4
编码
编码是计算机科学中的一个通用概念,它以一种专门的格式来表示字符,以便有效地传输或存储。
所有计算机文件类型都以特定的结构编码。
例如,当您上传 PDF 时,编码可能如下所示:
1 JVBERi0xLjMKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZwovT3V0bGluZXMgMiAwIFIKL1BhZ2VzIDMgMCBS\
2 ID4+CmVuZG9iagoyIDAgb2JqCjw8IC9UeXBlIC9PdXRsaW5lcyAvQ291bnQgMCA+PgplbmRvYmoKMyAwIG9i\
3 ago8PCAvVHlwZSAvUGFnZXMKL0tpZHMgWzYgMCBSCl0KL0NvdW50IDEKL1Jlc291cmNlcyA8PAovUHJvY1Nl\
4 dCA0IDAgUgovRm9udCA8PCAKL0YxIDggMCBSCj4+Cj4+Ci9NZWRpYUJveCBbMC4wMDAgMC4wMDAgNjEyLjAw\
5 MCA3OTIuMDAwXQogPj4KZW5kb2JqCjQgMCBvYmoKWy9QREYgL1RleHQgXQplbmRvYmoKNSAwIG9iago8PAov\
6 Q3JlYXRvciAoRE9NUERGKQovQ3JlYXRpb25EYXRlIChEOjIwMTUwNzIwMTMzMzIzKzAyJzAwJykKL01vZERh\
7 dGUgKEQ6MjAxNTA3MjAxMzMzMjMrMDInMDAnKQo+PgplbmRvYmoKNiAwIG9iago8PCAvVHlwZSAvUGFnZQov\
8 UGFyZW50IDMgMCBSCi9Db250ZW50cyA3IDAgUgo+PgplbmRvYmoKNyAwIG9iago8PCAvRmlsdGVyIC9GbGF0\
9 ZURlY29kZQovTGVuZ3RoIDY2ID4+CnN0cmVhbQp4nOMy0DMwMFBAJovSuZxCFIxN9AwMzRTMDS31DCxNFUJS\
10 FPTdDBWMgKIKIWkKCtEaIanFJZqxCiFeCq4hAO4PD0MKZW5kc3RyZWFtCmVuZG9iago4IDAgb2JqCjw8IC9U\
11 eXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQovTmFtZSAvRjEKL0Jhc2VGb250IC9UaW1lcy1Cb2xkCi9FbmNv\
12 ZGluZyAvV2luQW5zaUVuY29kaW5nCj4+CmVuZG9iagp4cmVmCjAgOQowMDAwMDAwMDAwIDY1NTM1IGYgCjAw\
13 MDAwMDAwMDggMDAwMDAgbiAKMDAwMDAwMDA3MyAwMDAwMCBuIAowMDAwMDAwMTE5IDAwMDAwIG4gCjAwMDAw\
14 MDAyNzMgMDAwMDAgbiAKMDAwMDAwMDMwMiAwMDAwMCBuIAowMDAwMDAwNDE2IDAwMDAwIG4gCjAwMDAwMDA0\
15 NzkgMDAwMDAgbiAKMDAwMDAwMDYxNiAwMDAwMCBuIAp0cmFpbGVyCjw8Ci9TaXplIDkKL1Jvb3QgMSAwIFIK\
16 L0luZm8gNSAwIFIKPj4Kc3RhcnR4cmVmCjcyNQolJUVPRgo=.....
这是一个 Base64 编码的 PDF 字符串。像这样的数据通常在上传 PDF 文件时被传递到服务器。
Base64 编码
btoa()
函数从一个字符串创建一个 Base64 编码的 ASCII 字符串。字符串中的每个字符都被视为一个字节(8 位:8 个 0 和 1)。
.atob()
函数对使用 Base64 编码的数据字符串进行解码。例如,Base64 编码字符串中的字符串“hello I love learning to computer program”如下所示:agvsbg 8 GSS BSB 3 zlig xlyxjuaw 5 nihrvignvbxb 1 dgvyihby B2 dyyw 0。
1 btoa('hello I love learning to computer program');
2 // aGVsbG8gSSBsb3ZlIGxlYXJuaW5nIHRvIGNvbXB1dGVyIHByb2dyYW0
1 atob('aGVsbG8gSSBsb3ZlIGxlYXJuaW5nIHRvIGNvbXB1dGVyIHByb2dyYW0');
2 // hello I love learning to computer program
在 https://en.wikipedia.org/wiki/Base64
了解 Base64 的更多信息。
字符串缩短
你有没有想过像这样的网址缩短网站。ly 工作?一种简化的 URL 压缩算法遵循一定的结构,如下图所示为 www.google.com
:
图 4-2
缩短后的数据库条目
- 整数 ID 被缩短为一个字符串。使用 Base62 编码缩短时,11231230 将是 VhU2。
图 4-1
数据库条目
- 数据库为 URL 创建一个唯一的基于整数的 ID。在图 4-1 ,
www.google.com
数据库中有条目 11231230。
对于缩短部分,可以使用下面的算法。有 62 个可能的字母和数字,由 26 个小写字母、26 个大写字母和 10 个数字(0 到 9)组成。
1 var DICTIONARY = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" .split(");
2
3 function encodeId(num) {
4 var base = DICTIONARY.length;
5 var encoded = " ;
6
7 if (num === 0 ) {
8 return DICTIONARY[0 ];
9 }
10
11 while (num > 0 ) {
12 encoded += DICTIONARY[(num % base)];
13 num = Math .floor(num / base);
14 }
15
16 return reverseWord(encoded);
17 }
18
19 function reverseWord(str) {
20 var reversed = "" ;
21 for (var i = str.length - 1 ; i >= 0 ; i-- ) {
22 reversed += str.charAt(i);
23 }
24 return reversed;
25 }
26
27 function decodeId(id) {
28 var base = DICTIONARY.length;
29 var decoded = 0 ;
30
31 for (var index = 0 ; index < id.split("" ).length; index++ ) {
32 decoded = decoded * base + DICTIONARY.indexOf(id.charAt(index));
33 }
34
35 return decoded;
36 }
37
38 console.log(encodeId(11231230 )); // prints 'VhU2'
39 console.log(decodeId('VhU2' )); // prints '11231230'
加密
在保护人们的在线信息时,加密极其重要。你在谷歌 Chrome 浏览器中见过图 4-3 中的警告吗?
图 4-3
SSL 警告
这可能意味着您尝试访问的网站没有正确的安全套接字层(SSL)证书。
图 4-4
TSL 过程
TSL 是一种标准的安全技术,用于在服务器和客户端(浏览器)之间建立加密链接。以下是 TSL 过程的简化步骤。在这个过程中,服务器对不同的密钥使用非对称加密进行加密和解密。浏览器只使用对称加密,即使用一个密钥来加密和解密数据。
-
服务器将其非对称公钥发送给浏览器。
-
浏览器为当前会话创建一个对称密钥,该密钥由服务器的非对称公钥加密。
-
服务器通过其私钥解密浏览器的会话,并检索会话密钥。
-
两个系统都有会话密钥,并将使用该密钥安全地传输数据。
这是安全的,因为只有浏览器和服务器知道会话密钥。如果浏览器第二天连接到同一个服务器,将会创建一个新的会话密钥。
SSL 警告消息表示浏览器和服务器可能没有加密该连接上的数据。
最常用的公钥加密算法是 RSA 算法。
RSA 加密
RSA 是一种基于分解大整数难度的加密算法。在 RSA 中,生成两个大素数和一个补充值作为公钥。任何人都可以用公钥加密信息,但是只有那些有质因数的人才能解码信息。
这个过程有三个阶段:密钥生成、加密和解密。
-
密钥生成:生成公钥(共享)和私钥(保密)。生成的密钥的构造方法也应该是保密的。
-
加密:秘密消息可以通过公钥加密。
-
解密:只有私钥可以用来解密消息。
以下是该算法的概述:
-
选择两个(通常是大的)素数, p 和 q 。
-
p 和 q 的乘积记为 n 。
-
( p -1)和( q -1)的乘积表示为φ。
-
-
选择两个指数, e 和 d 。
-
e 通常为 3。可以使用大于 2 的其他值。
-
d 是使得(e × d) % phi = 1 的值。
-
Encryption
process is as shown:
m - message:
m^e % n = c
c - encrypted message
Decryption process is as shown:
c^d % n = m
这是计算 d 的实现:
1 function modInverse(e, phi) {
2 var m0 = phi, t, q;
3 var x0 = 0, x1 = 1;
4
5 if (phi == 1)
6 return 0;
7
8 while (e > 1) {
9 // q is quotient
10 q = Math.floor(e / phi);
11
12 t = phi;
13
14 // phi is remainder now, process same as
15 // Euclid's algo
16 phi = e % phi, e = t;
17
18 t = x0;
19
20 x0 = x1 - q * x0;
21
22 x1 = t;
23 }
24
25 // Make x1 positive
26 if (x1 < 0)
27 x1 += m0;
28
29 return x1;
30 }
31 modInverse(7,40); // 23
还需要生成公钥和私钥的密钥对。
1 function RSAKeyPair(p, q) {
2 // Need to check that they are primes
3 if (! (isPrime(p) && isPrime(q)))
4 return;
5
6 // Need to check that they're not the same
7 if (p==q)
8 return;
9
10 var n = p * q,
11 phi = (p-1)*(q-1),
12 e = 3,
13 d = modInverse(e,phi);
14
15 // Public key: [e,n], Private key: [d,n]
16 return [[e,n], [d,n]]
17 }
让我们选择 5 和 11 作为质数,看看message
是 50 的例子。
1 RSAKeyPair(5,11); //Public key: [3,55], Private key: [27,55]
p = 5, 11
n = p x q = 55
phi = (5-1) x (11-1) = 4 x 10 = 40
e = 3
(e x d) % phi = 1 (3 x d) % 40 = 1
(81) % 40 = 1\. 81 = 3 x d = 3 x 27
d = 27
Encryption:
m - message: 50
m^e % n = c
50^3 % 55 = 40
Encrypted message.,c:
40
Decryption:
c^d % n = m
40^27 % 55 = 50
这完全加密了 50,而接收者可以将其解密回 50。通常,对于 RSA 算法,所选择的素数非常大。这是因为大数的质因数分解需要很长的计算时间。今天的标准是使用 4096 位的 prime 产品。即使是先进的计算机,计算它的质因数也需要数年时间。图 4-5 显示了 4096 位数的最大可能值。
图 4-5
2 4096
摘要
本章涵盖了各种本机实现的字符串函数,并在表 4-1 中进行了总结。
表 4-1
字符串函数摘要
|
功能
|
使用
|
| --- | --- |
| charAt(index)
| 在index
访问单个字符 |
| substring(startIndex, endIndex)
| 访问从startIndex
到endIndex
的部分字符串 |
| str1 > str2
| 如果str1
在字典上比str2
大,则返回true
|
| indexOf(str, startIndex)
| 从startIndex
开始的期望str
的索引 |
| str.split(delimiter)
| 用指定的delimiter
将一个字符串拆分成一个数组 |
| str.replace(original,new)
| 用new
替换original
|
此外,JavaScript 原生Regex
对象可以用于常用的字符串验证。表 4-2 提供了一个总结。
表 4-2
正则表达式摘要
|
正则表达式模式
|
使用
|
| --- | --- |
| /\d+/
| 任何数字字符 |
| /^\d+$/
| 仅数字字符 |
| /^[0-9]*.[0-9]*[1-9]+$/
| 浮点数字字符 |
| /[a-zA-Z0-9] /
| 仅字母数字字符 |**
版权属于:月萌API www.moonapi.com,转载请注明出处