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;};
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 三岁宝宝说话少怎么办 快4岁不会说话怎么办 宝宝2岁半不爱说话怎么办 两岁半宝宝注意力不集中怎么办 中国出生的外籍小孩怎么办签证 中国人入外籍后国内财产怎么办 中国人入外籍后国内资产怎么办 小孩去美国上小学怎么办 咳嗽震的胸口疼怎么办 高中孩子对手机着迷怎么办 小孩不肯读书沉迷游戏怎么办 小孩沉迷吃鸡游戏怎么办 高一数学成绩差怎么办 小孩子学数学用手指算怎么办 孩子d和b分不清怎么办 和家人走散后怎么办幼儿教案 小孩胃口不好不爱吃饭怎么办 幼儿园孩子学习记不住怎么办 幼儿园小孩数字记不住怎么办 大班教案走丢了怎么办 ppt加视频反了怎么办 拔罐之后背疼怎么办 拔完火罐后背疼怎么办 打印机红色的口堵了怎么办 打印机红色复印不出来怎么办 打印机加错颜色墨水怎么办 中班安全教案脚扭伤了怎么办 中班脚扭伤了怎么办教案 中班安全脚扭伤了怎么办 中班安全脚扭伤了怎么办反思 走丢了怎么办教案反思 汽车后轱辘不转怎么办 走丢了怎么办社会教案 小老鼠搬鸡蛋鸡蛋太大怎么办 小班走丢了怎么办教案 小班走丢了怎么办反思 房屋外墙漏水物业不管怎么办 厨房墙砖用色花怎么办 小孩子做错事很偏激怎么办 孩子在学校偷钱怎么办 房间墙壁上到处有湿虫怎么办