Skip to content
imshengli blog
Go back

JavaScript 字符串:常用方法、模板字符串与 Unicode

JavaScript 字符串操作大全:常用方法分类、模板字符串、正则配合、Unicode 处理与实际应用。

· 5 min

总结

JavaScript 的字符以 UTF-16 格式存储,每个字符占两个字节;对于补充平面字符(码点大于 U+FFFF),每个字符占四个字节,length 为 2。字符串一旦创建不可变,无法修改单个字符。

创建字符串

// 字面量
var str1 = 'hello';
var str2 = "world";

// String 转换
String(123);   // "123"
String(true);  // "true"
String(null);  // "null"

多行字符串用反斜杠续行(反斜杠后不能有空格)或字符串拼接:

var longString = 'Long \
long \
string';
// "Long long string"

转义字符

反斜杠(\)表示特殊字符:\n 换行、\t 制表符、\\ 反斜杠、\' 单引号、\" 双引号、\0 null。

特殊表示法:

字符串不可变性

var s = 'hello';
s[1] = 'a';   // 无效
delete s[0];  // 无效
s // "hello"

所有”修改”操作都返回新字符串,不改变原字符串。

常用方法

查找

var str = 'Hello World, Hello JS';

str.indexOf('Hello');       // 0
str.lastIndexOf('Hello');   // 13
str.indexOf('Hello', 1);   // 13(从位置 1 开始搜索)

str.includes('World');      // true
str.startsWith('Hello');    // true
str.endsWith('JS');         // true

str.search(/world/i);      // 6(支持正则)

截取

var str = 'Hello World';

// slice(start, end):支持负数索引
str.slice(0, 5);     // "Hello"
str.slice(6);        // "World"
str.slice(-5);       // "World"

// substring(start, end):不支持负数
str.substring(0, 5); // "Hello"

// 推荐使用 slice,语义更清晰

替换

var str = 'hello world hello';

str.replace('hello', 'hi');       // "hi world hello"(只替换第一个)
str.replace(/hello/g, 'hi');      // "hi world hi"(全局替换)

// 替换函数
'abc123'.replace(/\d+/, function(match) {
  return Number(match) * 2;
});
// "abc246"

分割与拼接

'a,b,c'.split(',');         // ["a", "b", "c"]
'hello'.split('');          // ["h", "e", "l", "l", "o"]
'a,b,c,d'.split(',', 2);   // ["a", "b"]

'Hello'.concat(' ', 'World'); // "Hello World"

大小写与去空格

'Hello'.toUpperCase();     // "HELLO"
'Hello'.toLowerCase();     // "hello"
'  hello  '.trim();        // "hello"
'  hello  '.trimStart();   // "hello  "
'  hello  '.trimEnd();     // "  hello"

其他

'ha'.repeat(3);          // "hahaha"
'5'.padStart(3, '0');    // "005"
'hi'.padEnd(5, '.');     // "hi..."
'abc'.charAt(1);         // "b"
'abc'.charCodeAt(0);     // 97

模板字符串

ES6 模板字符串使用反引号,支持多行和表达式插值:

var name = 'World';
var greeting = `Hello ${name}!`; // "Hello World!"

// 多行
var html = `
<div>
  <p>${greeting}</p>
</div>
`;

// 表达式和函数调用
var a = 10, b = 20;
`${a} + ${b} = ${a + b}`;  // "10 + 20 = 30"

标签模板(Tagged Template):

function highlight(strings, ...values) {
  return strings.reduce(function(result, str, i) {
    return result + str + (values[i] ? '<em>' + values[i] + '</em>' : '');
  }, '');
}

var user = 'Tom';
highlight`User ${user} logged in`;
// "User <em>Tom</em> logged in"

正则配合

// match:返回匹配数组
'test 123 hello 456'.match(/\d+/g);  // ["123", "456"]

// 捕获组
var result = '2018-01-15'.match(/(\d{4})-(\d{2})-(\d{2})/);
result[1]; // "2018"
result[2]; // "01"
result[3]; // "15"

// split 配合正则
'a1b2c3'.split(/\d/);  // ["a", "b", "c", ""]

// replace 中使用捕获组
'2018-01-15'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$2/$3/$1');
// "01/15/2018"

Unicode 处理

对于码点大于 U+FFFF 的字符(如 emoji),JavaScript 将其视为两个字符:

'𝌆'.length;  // 2
'😀'.length;  // 2

// 正确获取长度
Array.from('😀hello').length;  // 6

// ES6 码点方法
'𝌆'.codePointAt(0);           // 119558
String.fromCodePoint(119558);  // "𝌆"

// for...of 能正确遍历四字节字符
for (var ch of '😀hi') {
  console.log(ch); // 😀, h, i
}

Base64 编码

用于将二进制数据或不可打印字符转为可打印的 ASCII 字符:

btoa('Hello World!'); // "SGVsbG8gV29ybGQh"
atob('SGVsbG8gV29ybGQh'); // "Hello World!"

// 非 ASCII 字符需要先编码
function b64Encode(str) {
  return btoa(encodeURIComponent(str));
}
function b64Decode(str) {
  return decodeURIComponent(atob(str));
}
b64Encode('你好'); // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE'); // "你好"

实际应用

URL 参数解析

function parseQuery(queryString) {
  return queryString.replace(/^\?/, '').split('&')
    .reduce(function(params, pair) {
      var parts = pair.split('=');
      params[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1] || '');
      return params;
    }, {});
}
parseQuery('?name=Tom&age=20'); // { name: "Tom", age: "20" }

驼峰与短横线转换

function toCamelCase(str) {
  return str.replace(/-([a-z])/g, function(match, letter) {
    return letter.toUpperCase();
  });
}
toCamelCase('background-color'); // "backgroundColor"

function toKebabCase(str) {
  return str.replace(/[A-Z]/g, function(letter) {
    return '-' + letter.toLowerCase();
  });
}
toKebabCase('backgroundColor'); // "background-color"

参考链接


Share this post on:

Previous Post
JavaScript 函数式编程:纯函数、柯里化与组合
Next Post
ES6 Promise:从链式调用到手写实现