ECMAScript6(4):字符串类型扩展
来源:互联网 发布:下载云端软件 编辑:程序博客网 时间:2024/06/06 02:54
相关文章
ECMAScript6 (1):块级作用域
ECMAScript6 (2):解构赋值
ECMAScript6 (3):数值类型扩展
由于 CSDN 不支持 utf-32 字符集,本文 unicode 部分存在一些乱码,全文中的”��” 表示一个汉字(上土下口),非乱码文章请查看 github
unicode
javascript 本可以表示 unicode, ES5 可以直接表示 utf-16 的字符集, 但如果需要表示 utf-32 的字符集就多有不便, 需要使用2个 utf-16 的编码。ES6就这个问题进行了改进, 且与原表示符是等价的(理论上是这样的, 但 js 不能保证都识别正确):
//ES5"\uD842\uDFB7" //"��"//ES6"\u{20BB7}" //"��""\uD842\uDFB7" === "\u{20BB7}"; //true"\u01d1" === "\u004f\u030C"; //理论上是一致的, 但 js 返回了 false//使用 normalize 统一编码来解决这个问题"\u01d1".normalize() === "\u004f\u030C".normalize(); //true
遗憾的是, normalize()
方法只能表示2个 utf-16 字符的合成, 要是3个或以上就只能自己用正则表达式解决了。
至此, 一个字符有了6中表示方法:
//以下结果都是 true"\x7A" === "z";"\u{7A}" === "z";"\u007A" === "z";"\172" === "z";"\z" === "z";
javascript内部用 utf-16 格式存储字符, 这样仓促的引入 utf-32 的码点会引起许多错误, 所以 ES6 在 String.prototype
上添加了 CodePointAt()
方法替换 charCodeAt()
, 用静态方法 String.fromCodePoint()
替换了 String.fromCharCode()
, 以解决因编码差异导致的计算错误。
但是, 我们依然要注意到一下错误:
var a="��a";console.log(a.length); //3console.log(a.charAt(0)); //"\uD842"console.log(a.split('')); //["\uD842", "\uDFB7", a]//这些显然不是我们想要的, 我们需要替换使用console.log(a.codePointLength()); //下面我们可以自己简单写一个 codePointLength() 方法console.log(a.at(0)); //"��", ES7 方法, babel中有console.log(a.toArray()); //下面我们可以自己简单写一个 toArray() 方法
为此, 遍历字符串中的每个字符, 请使用 for…of
var a="��a";for(let alpha of a){ console.log(alpha); //依次输出: ��, a}
除此之外, ES6 还提供了一些其他的简单方法, 这里简单带过:
//动态方法s.includes(str, n); //s从下标 n 的字符起是否包含 str 字符串, 返回 Boolean, n 默认为 0s.startsWith(str, n); //s从下标 n 的字符起是否以 str 开头, 返回 Boolean, n 默认为 0s.endWith(str, n); //s的前 n 个字符是否以 str 结尾, 返回 Boolean, n 默认为字符串长度s.repeat(n); //返回将 s 重复 n 次的新字符串, 如果 n 是小数, 会向下取整;如果 n 是 infinity 或小于等于-1 会报错;如果 n 大于-1且小于等于零, 返回空字符串;如果 n 为 NaN, 返回空字符串;其余传输参数遵循隐式类型转换。s.padStart(minLen, str); //对于小于 minLen 长度的字符串, 在 s 前用 str 重复补充为 len 长度, 返回该新字符串, 否则返回原字符串。str默认为空格s.padEnd(minLen, str); //对于小于 minLen 长度的字符串, 在 s 后用 str 重复补充为 len 长度, 返回该新字符串, 否则返回原字符串。str默认为空格
自定义函数计算字符串长度和大小, 以及转化为数组:
//计算字符串长度, 方法1String.prototype.codePointLength = function(){ var result = this.match(/[\s\S]/gu); return result ? result.length : 0;};//计算字符串长度, 方法2String.prototype.codePointLength2 = function(){ return [...this].length;};//计算字符大小String.prototype.size = function(){ var size = 0; for(let alpha of this){ if(alpha.codePointAt(0) > 0xFFFF){ size+=4; } else { size+=2; } } return size;};var a="��a";console.log(a.codePointLength()); //2console.log(a.codePointLength2()); //2console.log(a.size()); //6//字符串拆分为数组,方法1String.prototype.toArray = function(nil){ if(nil === undefined){ return Array.from(this); } if(nil.constructor === RegExp || nil.constructor === String){ var reg = new RegExp(nil, "u"); return this.split(reg); }}//字符串拆分为数组,方法2String.prototype.toArray2 = function(nil){ if(nil === undefined){ return [...this]; } if(nil.constructor === RegExp || nil.constructor === String){ var reg = new RegExp(nil, "u"); return this.split(reg); }}var a="��ds��asaf��saf";console.log(a.toArray()); //["��", "d", "s", "��", "a", "s", "a", "f", "��", "s", "a", "f"]console.log(a.toArray('a')); //["��ds��", "s", "f��s", "f"]console.log(a.toArray('��')); //["", "ds", "asaf", "saf"]console.log(a.toArray2()); //["��", "d", "s", "��", "a", "s", "a", "f", "��", "s", "a", "f"]console.log(a.toArray2('a')); //["��ds��", "s", "f��s", "f"]console.log(a.toArray2('��')); //["", "ds", "asaf", "saf"]
模板字符串
ES5 中, 我们写一个多行字符很不方便:
//我们这样写动态字符串var multiStr = "I am " + name; //假定 name 已定义//这样写多行字符串var multiStr = "first line\nsecond line\nthird line";//在或者这样var tempArr = ["first line", "second line", "third line"]; //多用于生成动态字符串。此外《编写高质量代码:改善JavaScript程序的188个建议》中指出, 这个方法写静态字符串一样比加号(+)性能更好var multiStr = tempArr.join("\n");
在 ES6 中利用反引号(`...`
)和EL表达式(${...}
), 我们可以这样:
//我们这样写动态字符串var multiStr = `I am ${name}`; //假定 name 已定义//这样写多行字符串var multiStr = `first linesecond linethird line`;
注意: 反引号中的所有空格和缩进都会被保留下来
EL表达式中可以放入任何表达式进行运算:
var x=2, y=3;console.log(`x+y=${x+y}`); //x+y=5function plus(a, b){ return a+b;}console.log(`x+y=${plus(x, y)}`); //x+y=5
引用模板字符串本身:
//方法1let str = 'return ' + '`Hello ${name}`';let fun = new Function('name', str);fun('Jack');//方法2let str2 = '(name) => `Hello ${name}`';let fun2 = eval(str2);fun2('Jack');
标签模板
标签模板是用来处理字符串的函数, 但是调用方式和以往大不相同, 是直接将模板字符串跟在函数名后面, 该函数的结构如下:
function funName(strings, ...values){ //...}
其中, 以EL表达式作为分界, 前后和表达式之间的字符串部分, 会从左到右依次放入 strings
参数中;每一个 EL 表达式会从左到右依次放入 values
参数中:
function tag(strings, ...values){ console.log(strings[0]); console.log(strings[1]); console.log(strings[2]); console.log(values[0]); console.log(values[1]); return 'OK';}//当然, 也可以这样写(关于展开运算符, 这里不做深入讨论, 具体在 ES6 的函数部分展开)function tag(strings, value0, value1){ console.log(strings[0]); console.log(strings[1]); console.log(strings[2]); console.log(value0); console.log(value1); return 'OK';}
下面是完整的调用:
var a = 5;var b = 10;function tag(strings, ...values){ console.log(strings[0]); //"Hello " console.log(strings[1]); //" world " console.log(strings[2]); //"!" console.log(values[0]); //15 console.log(values[1]); //50 return 'OK';}console.log(tag`Hello ${a+b} world ${a*b}!`); //"OK"
当然, 标签模板的正经用法如下:
var a = 5;var b = 10;function tag(strings, ...values){ var result = [], i = 0; while(i < strings.length){ result.push(strings[i]); if(values[i]){ result.push(values[i]); } i++; } return result.join('');}console.log(tag`Hello ${ a + b } world ${ a * b}!`); //Hello 15 world 50!
当然, 如果将上方 tag 函数中的 <
, >
, &
都替换掉, 并忽略 values
中的内容, 可以用来过滤用户输入数据, 防止恶意代码注入。
值得一提的是, tag的第一个参数 strings 还有一个 raw 属性, 也是一个数组, 内容分别对应 strings 数组的值的原生字符。比如 strings 中 strings[0]=“a\nb"
, 则 strings.raw[0]="a\\nb"
。除此之外, ES6 还添加了 String.raw()
方法, 用于解析模板字符串, 但返回值的字符串是原生字符, 其内部基本如下:
String.raw = function(strings, ...values){ var output = ""; for(var index = 0; index < values.length; index++){ output += strings.raw[index] + value[index]; } output += string.raw[index]; retrun output;};
- ECMAScript6(4):字符串类型扩展
- ECMAScript6(3):数值类型扩展
- ECMAScript6笔记:字符串的扩展
- ECMAScript6-学习笔记(字符串的扩展)
- ECMAScript6笔记:字符串的扩展(2)
- ECMAScript6.0学习之第五篇字符串的扩展
- ECMAScript6数值的扩展
- ECMAScript6标准数组的扩展
- ECMAScript6笔记:数值的扩展
- ECMAScript6笔记:数组的扩展
- ECMAScript6笔记:函数的扩展
- ECMAScript6笔记:对象的扩展
- ECMAScript6(5):函数的扩展
- ECMAScript6(6):数组的扩展
- ECMAScript6(8):对象的扩展
- ECMAScript6(10):Symbol基本类型
- ECMAScript6-学习笔记(数值的扩展)
- ECMAScript6-学习笔记(数组的扩展)
- TreeMap 嵌套
- D
- 51Nod--1008 N的阶乘 mod P
- linux系统java环境配置命令和MySql数据库之简化版(转自王大锤大神)
- K-means 和 K-medoids算法聚类分析
- ECMAScript6(4):字符串类型扩展
- BZOJ 1042 硬币购物 (数论 容斥)
- matlab保存figure中的图片去掉白边
- PHP防SQL注入记录
- 93 C语言数组指针(指向数组的指针)
- android studio的adb端口被占解决方法
- 自学Java之Java编程(序列化和查看对象)(016day)
- USACO-section 1.3 Prime Cryptarithm[hash]
- 解决configure: error: Please reinstall the libcurl