JavaScriptES6字符串拓展

JavaScriptES6上新增了很多字符串的方法。

目录

includes()

startsWith()

endsWith()

repeat()

padStart()、padEnd()

模板字符串

标签模板

String.raw


在以前版本中也有查找的方法,比如说indexOf(),就可以查找是否含有,但是这个方法返回的索引位,当找不到的时候返回的是-1,显然是很麻烦的。

ES6产生了3个查找字符串的方法:includes()、startsWith()、endsWith();

includes()

这个方法参数是查找的字符串,如果找到返回true,找不到返回false。

let str = "apple banana";'
console.log(str.includes("apple"))    //true

includes()方法可以支持第二个参数,表示开始搜索的位置。

let str = "apple banana";
console.log(str.includes("banana",6))    //true

startsWith()

这个方法表示查找原字符串是否以给定的字符串开头,开始的位置,返回Boolean,成功返回true,否则返回false

let str = "Hello";
console.log(str.startsWith("H"));    //true
console.log(str.startsWith("e"));    //false

这个方法也是可以支持第二个参数,表示开始搜索的位置

let str = "Hello";
console.log(str.startsWith("e",1));    //true

endsWith()

这个方法表示查找原字符串是否以给定的字符串结尾,返回Boolean类型,成功返回true,否则返回false

let str = "Hello world";
console.log(str.endsWith("world"));    //true

endsWith()支持第二个参数,表示搜索前n个字符。是指从第n + 1个位置搜索前n个字符。

let str = "Hello world";
console.log(str.endsWith("w",7))    //true

repeat()

返回一个新的字符串,表示将原字符串重复n次

console.log("x".repeat(3))    //xxx
console.log("hello".repeat(2))    //hello
console.log("hello".repeat(0))    //""    将原字符串重复0次返回空字符串
//如果参数是小数,会被取整(向下取整)
console.log("x".repeat(2.3))    //xx
//如果参数是负数或者Infinity,会报错
console.log("x".repeat(-1))    //error
console.log("x".repeat(Infinity))    //error
//但是,如果参数是在0 到 -1之间的小数的话,则等同于0,这是因为参数会先进行取整运算,0 到 -1之间的小数,取整以后等于 -0 repeat视为0;
console.log("x".repeat(-0.5))    //""
//如果参数为NaN的时候等同于0
console.log("x".repeat(NaN))    //""
//如果参数为字符串的话则先转换为数字,转换不成按照0计算
console.log("x".repeat("3"))    //xxx
console.log("x".repeat("str"))    //""

padStart()、padEnd()

ES2017引入了字符串补全的功能,如果某个字符串不够指定长度,会在头部或尾部补全,padStart()表示头部补全,padEnd()表示尾部补全。

两个方法都是支持两个参数,第一个参数是指定字符串的长度,第二个参数是不够长度补的字符串。

console.log("x".padStart(4,"a"))    //aaax
console.log("x".padEnd(4,"a"))    //xaaa

如果原字符串的长度大于指定的最小长度,则返回原字符串。

console.log("xxxx".padStart(3,"a"))    //xxxx
console.log("xxxx".padEnd(3,"a"))    //xxxx

如果用来补全的字符串与原字符串,二者的长度超过了指定的最小长度,则会截去超过位数的自妇产,然后补全字符串。

console.log("xxx".padStart(10,"0123456789"))    //0123456xxx
console.log("xxx".padEnd(10,"0123456789"))        //xxx0123456

如果省略第二个参数,则默认使用空格补全长度。

console.log("xxx".padStart(10))    //      xxx
console.log("xxx'.padEnd(10));    //xxx       

padStart的常见用途是为数值补全指定位数和用于提示或刷新字符串格式

console.log("1".padStart(10,"0"))    //0000000001
console.log("123".padStart(10,"0"))  //0000000123

//        提示/刷新
console.log("12".padStart(10,"YYYY-MM-DD"));    //YYYY-MM-12
console.log("09-12".padStart(10,"YYYY-MM-DD"))  //YYYY-09-12

模板字符串

传统的我们在写字符串的时候,需要引入变量的时候用字符串相加的方式引入,换行还需要用+号来连接,非常的繁琐,不方便,ES6引入了模板字符串解决了这个问题。

模块字符串(template string)是增强版的字符串。用反引号(`)标识。它可以当作普通字符串使用。也可以用来定义多行字符串,或者在字符串中嵌入变量。

//普通字符串
console.log(`In javascript \n is a line-feed`);
//多行字符串
console.log(`我正在学习
    javascriptES6
`)
//字符串中嵌入变量
let test = '123', time = 'today';
console.log(`今天是${time},我是${test}`);

如果在模板字符串中需要使用反引号。则前面要用反斜杠转义

let str = `
  this 
  is \`js\`
`.trim();
console.log(str);

如果使用模块字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。

div.innerHTML = `
    <ul>
       <li>1</li>
       <li>2</li>
    </ul>
 `

trim--使用模块字符串,空格和换行都会被保留,上面代码<ul>标签前面会有一个换行。如果你不想要换行,可以使用trim清除多行字符串中第一行字符串的换行。

div.innerHTML = `
<ul>
   <li>1</li>
   <li>2</li>
</ul>
`.trim();

模板字符串中嵌入变量,需要将变量名写在${}之中

let str = "abc";
let str1 = `this is ${str}`

在大括号内部可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。

let x = 1;
let y = 2;
console.log(`${x} + ${y} = ${x + y}`);    //1 + 2  = 3
console.log(`${x} + ${y * 2} = ${x + y * 2}`)    //1 + 4 = 5
let obj = {
    a : 1,
    b : 2,
}
console.log(`${obj.a + obj.b}`)    //3

模板字符串之中还可以调用函数,调用之后字符串为函数的返回值

function fu(){
    console.log(123);
    return 123;
}
console.log(`${fn()}`)    //123    123
//第一个123为函数中输出的,第二个为模板字符串中的

特别注意的是:如果大括号中的值不是字符串,将按照一般的规则转换成字符串。比如,大括号中是一个对象,将默认调用对象的toString方法。

如果模板字符串中的变量没有声明,将会报错

console.log(`${name}`)        //error

由于模板字符串的大括号内部就是执行的JavaScript代码,因此大括号内部是一个字符串,将会原样输出。

console.log(`Hello${`World`}`)    //HelloWorld

由于模板字符串内部就是执行的JavaScript代码,所以模板字符串开可以嵌套着使用,

const tmpl = addrs => `
    <table>
       ${addrs.map(addr =>`
            <tr>
                <td>${addr.name}</td>
                 <td>${addr.age}</td>
            </tr>
        `).join("")}
    </table>
`;
let data = [
    {name : "张三",age : 18,}
    {name : "李四",age : 20,}
],
console.log(tmpl(data));

如果需要引入模板字符串本身,在需要的时候执行,也是可以的

let str = 'return' + '`Hello ${name}`';
let fun = Function("name",str); 
console.log(fun("wang"))    /Hello wang
//先以字符串的形式定义好,在函数需要是使用

标签模板

模板字符串可以紧跟在一个函数名的后面,该函数将被调用来处理这个模板字符串,这被称为“标签模板”功能

alert`123`    //123

标签模板其实不是模板,而是函数调用的一种特殊形式,‘标签’指的就是函数,紧跟在后面的模板字符串就是它的参数。但是,如果模板字符串中有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。

let a = 5;
let b = 10;
tag`Hello ${a + b} world ${a * b}`; == tag(['Hello ', 'world',''],15,50)       
上面代码中,模板字符串前面有一个表示名tag,它是一个函数,整个表达式的返回值,就是tag函数处理模板字符串后的返回值。

函数tag依次会接受多个参数
 function tag(stringArr,value1,value2){
     // .....
}
//等同于
function tag(stringArr,...values){
    // ...
}

tag函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分,也就是说,变量替换只发生在第一个成员和第二个成员之间;第二个成员和第三个成员之间,以此类推。

tag函数的其他参数,都是模板字符串各变量被替换后的值,由上为例,tag函数会接受到三个参数
      tag函数的参数:  第一个参数['Hello ' , 'world ',''];
                     第二个参数15
                     第三个参数50
也就是说tag函数的实际调用时tag(['Hello ','world ',''],15,50);
let a = 5;
let b = 10;
let tag = (s,v1,v2) =>{
      console.log(s[0]);  //Hello
      console.log(s[1]);  //world
      console.log(s[2]);  //""
      console.log(v1);    //15
      console.log(v2);    //50
}
tag`Hello${a + b}world${a * b}`;  

下面是一个更复杂的例子,将各个参数按照原来的位置拼合回去

let totle = 30;
function passthru(literals){
    let result = "";
    let i = 0;
    while(i < literals.length){
        result += literals[i ++];
        if(i < arguments.length){
            restlt += arguments[i];
        }
    }
    return result;
}
console.log(passthru`The totle is ${title}(${totle * 10.5} is max)`)

passthru函数采用rest参数的写法如下

let passthru = (literals, ...values) => {
    let output = "";
    let index;
    for(index = 0; index < values.length ; index ++){
         output += literals[index] + values[index];
     }
     output += literals[index];
     return output;
};
let msg = passthru`The totle is ${totle}(${totle * 10.5} with t)`;
console.log(msg);

标签模板'的一个重要的作用,就是过滤HTML字符串,防止用户输入恶意内容\

function SaferHTML(templateDate){
   let s = templateDate[0];
   for(let i = 1 ; i < arguments.length ; i++){
        let arg = String(arguments[i]);
        s += arg.replace(/&/g,"&amp;")
                .replace(/</g,"&lt;")
                .replace(/>/g,"&gt;");
        s += templateDate[i];
    }
    return s;
}
let sender = `<script>alert("abc")<script>`;
let message = SaferHTML`<p>${sender} has sent you a message.</p>`;

模板处理函数的第一个参数(模板字符串数组),还有一个raw属性

console.log`123`;   //["123",raw: Array(1)];
上面代码中console.log接受到的参数,实际上是一个数组,该数组有个raw属性,保存的是转义后的原字符串
let tag = (strings) => {
    console.log(strings.raw[0]);    //First line\nSecond line
}
tag`First line\nSecond line`;
上面代码中,tag函数的第一个参数strings,有一个raw属性,也指向一个数组,该数组的成员与strings数组完全一致,二者唯一 的区别就是字符串里面的斜杠被转义了,
比如strings.raw数组会将\n 视为 \\  n两个字符,而不是换行符,这是为了方便取得转义之前的原始模板而设计的

String.raw

ES6还为原生的String对象,提供了一个raw方法。

string.raw方法,往往用来充当模板字符串的处理函数,返回一个斜杠都被转义(即,斜杠前再加一个斜杠)的字符串,对应于替换变量后的模板字符串。

console.log(String.raw`Hi\n${2 + 3}`);  //Hi\n5
console.log(String.raw`Hi\u000A`);      //Hi\u000A
console.log(`Hi\n${2 + 3}`);            // Hi     5 

如果原字符串的斜杠已经转义,那么String.raw会再次进行转义

console.log(String.raw`\\n`);

String.raw方法可以作为处理模板字符串的基本方法,它将所有的变量替换,而且对斜杠进行转义,方法下一步作为字符串来使用。String.raw方法也可以作为正常的函数来使用,这时,它的第一个参数应该是一个具有raw属性的对象,,且raw属性的值应该是一个数组。

let arr = [];
let obj = { raw: 'test' };
let len = obj.raw.length;
for(let i = 0; i < len - 1; i++){
      arr[i] = " ";
}
arr.unshift(obj);
console.log(String.raw.apply(null,arr));
console.log(String.raw({ raw : 'test'},0,1,2));  等同于  console.log(String.raw({raw : ['t','e','s','t']},0,1,2));

String.raw作为函数 原理代码

String.raw = function(strings,...values){
   let output = '';
   let index;
   for(index = 0; index < values.length; index ++){
        output += strings.raw[index] + values[index];
   }
   output += strings.raw[index];
   return output;
}
console.log(String.raw({ raw: 'test' }, 0, 1, 2));    //t0e1s2t

主页传送门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值