ES6-字符串和正则表达式


title: ES6-字符串和正则表达式
date: 2018-01-30 22:15:59
tags: es6


timg.jpg

前言

入行这么久了,前端学习的成本感觉越来越高了,不会的东西一茬接一茬,在学校太忽视它,学的半吊子,现在要努力赶上才行,杭州的天气变冷了,我也想回家了,坚持,哎嘿,再上半个月班就要放假了开心。(这是从我自己博客移植过来的)

我的博客地址 :http://www.aymfx.cn/,欢迎访问

引子

这张理解起来比较费劲,慢慢看,慢慢练,天气比较冷啊,手敲这些好费劲

utf-16码位(基本多文种平面)到辅助平面字符的扩展

在ES6之前, JS 的字符串以 16 位字符编码(UTF-16)为基础。每个 16 位序列(相当于2个字节)是一个编码单元(code unit),可简称为码元,用于表示一个字符。字符串所有的属性与方法(如length属性与charAt() 方法等)都是基于16位序列

最常用的Unicode字符使用16位序列编码字符,属于“基本多语种平面”(Basic Multilingual Plane BMP),也称为“零断面”(plan 0), 是Unicode中的一个编码区段,编码介于\u0000~\uFFFF之间。超过这个范围的码位则要归属于某个辅助平面或称为扩展平面(supplementary plane),其中的码位仅用16位就无法表示了 为此,UTF-16引入了代理对(surrogate pairs),规定用两个16位编码来表示一个码位。这意味着,字符串里的字符有两种:一种由一个码元(共 16 位)来表示BMP字符,另一种用两个码元(共 32 位)来表示辅助平面字符

let text = '?'

console.log(text.length); //2
console.log(/^.$/.test(text)); //false
console.log(text.charAt(0)); //�
console.log(text.charAt(1)); //�
console.log(text.charCodeAt(0)); //55362
console.log(text.charCodeAt(1)); //57271

这个字?(jí)其实就是一个两个16位字符组成的字,基于16位字符串的属性与方法便失效了

codePointAt() 只接受编码单元的位置而非字符位置作为参数,返回给定位置对应的码位

let text = 'a?'

console.log(text.charCodeAt(0)); //55362
console.log(text.charCodeAt(1)); //57271
console.log(text.charCodeAt(2)); //57271

console.log(text.codePointAt(0)); //134071
console.log(text.codePointAt(1)); //57271
console.log(text.codePointAt(2)); //57271

通过这个方法我们可以检测字符是不是32位的

function is32Bit(char){
    return char.codePointAt(0) > 0xffff;
    
}

console.log(is32Bit('?')); //ture
console.log(is32Bit('a'));  //false

String.fromCodePoint()通过码位获得对应字符

  console.log(String.fromCodePoint(134071)); //?

normalize()

许多欧洲语言有语调符号和重音符号。为了表示它们,Unicode提供了两种方法。一种是直接提供带重音符号的字符,比如Ǒ(\u01D1)。另一种是提供合成符号(combining character),即原字符与重音符号的合成,两个字符合成一个字符,比如O(\u004F)和ˇ(\u030C)合成Ǒ(\u004F\u030C)。
这两种表示方法,在视觉和语义上都等价,但是JavaScript不能识别。

'\u01D1'==='\u004F\u030C' //false

'\u01D1'.length // 1
'\u004F\u030C'.length // 2
'\u01D1'.normalize() === '\u004F\u030C'.normalize() // true

  • NFC,默认参数,表示“标准等价合成”(Normalization Form Canonical Composition),返回多个简单字符的合成字符。所谓“标准等价”指的是视觉和语义上的等价。
  • NFD,表示“标准等价分解”(Normalization Form Canonical Decomposition),即在标准等价的前提下,返回合成字符分解的多个简单字符。
  • NFKC,表示“兼容等价合成”(Normalization Form Compatibility Composition),返回合成字符。所谓“兼容等价”指的是语义上存在等价,但视觉上不等价,比如“囍”和“喜喜”。(这只是用来举例,normalize方法不能识别中文。)
  • NFKD,表示“兼容等价分解”(Normalization Form Compatibility Decomposition),即在兼容等价的前提下,返回合成字符分解的多个简单字符

正则表达式u修饰符

let text = '?'
console.log(/^.$/.test(text)); //false
console.log(/^.$/u.test(text)); //true

计算码位的数量

function codePointLength(text){
    let result = text.match(/[\s\S]/gu);
    return result ? result.length : 0;
}
console.log(codePointLength("123a")); //4
console.log(codePointLength("?a")); //2
console.log(codePointLength("?哦")); //2


//emmmmm。运行效率蛮低,听说有更简单的,后面演示

字符串中子串的识别

includes(x,y)检测指定字符串返回boolean值,第二参数是开始位置(0开始数)

let text = "adsdasdasgsgwefsfs";
let subtext = 'asd';
console.log(text.includes(subtext,4)) //true
console.log(text.includes(subtext)) //true
console.log(text.includes('sdadasda')) //false

startsWith(x,y) 和 endsWith(x,y) 检测字符串开头和结尾的是否与子串相匹配,第二参数是开始位置(0开始数)

let text = "adsdasdasgsgwefsfs";
let subtext1 = 'ads';
let subtext2 = 'sfs';

console.log(text.startsWith('asd',4)) //true
console.log(text.startsWith(subtext1)) //true
console.log(text.startsWith('sdadasda')) //false


console.log(text.endsWith('gsgwefsfs',18)) //true 以最后一个字母的位置为准
console.log(text.endsWith(subtext2)) //true
console.log(text.endsWith('sdadasda')) //false

repeat() 接受一个number,即将字符重复的次数

console.log('x'.repeat(6)); // xxxxxx
console.log('ly'.repeat(3));  //lylyly
console.log('爱'.repeat(2));  //爱爱

正则的语法变更 (蛮头疼的,正则还是晕乎乎的)

正则表达式y修饰符

除了u 修饰符,ES6还为正则表达式添加了 y 修饰符,叫做“粘连”修饰符。y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g 修饰符只要剩余位置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的含义,当为匹配到时,将会返回空,lastIndex将会置为0

var s = 'aaa_aa_a';  
var r1 = /a+/g;  
var r2 = /a+/y;  
  
console.log(r1.exec(s)) //["aaa", index: 0, input: "aaa_aa_a"] console.log(r2.exec(s)) //["aaa", index: 0, input: "aaa_aa_a"]
console.log(r1.lastIndex) //3
console.log(r2.lastIndex) //3


console.log(r1.exec(s)) //["aa", index: 4, input: "aaa_aa_a"]
console.log(r2.exec(s)) //null  
console.log(r1.lastIndex) //6
console.log(r2.lastIndex) //0



console.log(r1.exec(s)) //["a", index: 7, input: "aaa_aa_a"]
console.log(r2.exec(s)) //["aaa", index: 0, input: "aaa_aa_a"] console.log(r1.lastIndex) //8
console.log(r2.lastIndex) //3

检测y修饰符是否存在

let pattern = /hello\d/y;

console.log(pattern.sticky) //true  谷歌浏览器下

正则表达式的复制

es5 如下复制

var re1 = /ab/i
    re2 = new RegExp(re1);
    console.log(re1.construct === re2.construct) //true

es6新增了可以添加传修饰符

var re1 = /ab/i
    re2 = new RegExp(re1,'g');
    console.log(re1.toString()) ///ab/i
    console.log(re2.toString()) ///ab/g

flags属性

source获取正则表达式文本 flags获取其修饰符

let re = /ab/gi;


console.log(re.source); //ab
console.log(re.flags);  //gi

模板字面量

JS 的字符串相对其他语言来说功能总是有限的,事实上,ES5中一直缺乏许多特性,如多行字符串、字符串格式化、HTML转义等。ES6通过模板字面量的方式进行了填补,模板字面量试着跳出JS已有的字符串体系,通过一些全新的方法来解决类似的问题

反引号(``)

const name = 'ly';
let message = `${name},is a man`  //ly,is a man
console.log(message);

//${} 可以写变量  名叫字符串占位符

console.log(`\`hh\``); //`hh`

//es5 实现多行文本
var message = " ly  \n \
   love you"
console.log(message);

//es6

var message = ` ly
   love you`
console.log(message); // ly
                      // love you

字符串占位符 ${javascript表达式}

let count = 15,
    price = .5,
    message = `${count} items cost $${(count*price).toFixed(1)}`;
    console.log(message); //15 items cost $7.5

标签模板

标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的是函数,紧跟在后面的模板字符串就是它的参数

var a = 5;
var b = 10;
tag `Hello ${a+b} world ${a*b}`;
//这个标识名tag,它是一个函数。整个表达式的返回值,就是tag函数处理模板字符串之后的返回值。函数tag会依次接收到多个参数。

tag函数的第一个参数是一个数组,该数组的成员时模板字符串中那些没有变量替换的部分,也就是说,变量替换只发生在数组的第一个成员和第二个成员之间,以此类推。tag函数的其他参数都是模板字符串各个变量被替换后的值,由于本例中,模板字符串含有两个变量,因此tag会接收到value1和value2两个参数。
tag函数所有参数的实际值如下:
——第一个参数:['Hello ',' world ','']
——第二个参数:15
——第三个参数:50
也就是说tag函数实际上是以下面的形式调用的
tag(['Hello ',' world ',''],15,50);
我们可以按照需要编写tag 函数的代码。

var count = 5;
var price = 10;

function tag(s,v1,v2,v3){
    console.log(s[0]);
    console.log(s[1]);
    console.log(s[2]);
    console.log(s);
    console.log(v1);
    console.log(v2);
    return 'ok'
}
tag`q${count} items cost $${(count*price).toFixed(1)}.`;

//VM173:5 
//VM173:6  items cost $
//VM173:7  .
//VM173:8 5
//VM173:9 50.0
//ok

标签函数的常用形式

function tag(literals,...substitutions){
    //literals 值得是被${}隔开的字符
    //substitutions,有几个${}就有几个这个
}

利用 literals.length-1 === substitutions.length,拼接字符串

function passthru(literals,...values){
    var output ="";
    for(var index = 0;index<values.length;index++){
        output = literals[index]+values[index];
    }
    output+=literals[index];
    return output;
}

let count = 15,
    price = .5,
    message = passthru`${count} items cost $${(count*price).toFixed(1)}`;
    console.log(message); //15 items cost $7.5

what?这样做的意义是啥?

emmm,过滤html字符串,还有一些转义字符的过滤

function SaferHTML(templateData){
    var s = templateData[0];
    var i;
    for(i = 1;i<arguments.length;i++){
        var arg = String(arguments[i]);

        //sender里面可能有特殊字符,进行转义
        s += arg.replace(/&/g,"&amp;")
                .replace(/</g,"&lt;")
                .replace(/>/g,"&gt;");
        s += templateData[i];
    }
    console.log(i);//2,表示这个循环只执行了一次,因为templateData[0]="<p>",arguments这个数组只有${sender}这个元素,后面一长串字符都是templateData[2];
    return s;
}
var sender = '<script>alert("abc")</script>';
var message = SaferHTML`<p>${sender} has sent you a message.</p>`;
console.log(message);

在模板字面量中使用原始值

使用内建对象String.raw访问


let ms1 = `ly\n love you`
let ms2 = String.raw`ly\n love you`

console.log(ms1); //ly
                  //love you

console.log(ms2); // ly\n love you


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容