ECMAScript 6的一些注意点 第二部分(字符串拓展 -- 数值拓展)

标签模板

  • “标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。
  • 如果模板字符里面有变量,会将模板字符串先处理成多个参数,再调用函数。
  • 函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分。

假设有以下函数:

let a = 1;
let b = 2;
function tag(x,y){
    return x,y;
}
tag`this is ${a} and ${a+b}`;

注意,由于使用模板字符串形式,第一个参数会是一个只接收非变量的数组(存在一个raw属性,用来保存转以后的原字符串),所以这里会输出,可以看到输出参数并不全,因为非变量数组占用了一个变量位置:

["this is" , " and " , "" ] 1
//x即为存放非变量的数组,故y为第二个参数1

相当于这么调用的函数:

tag(["this is","and",""],1,3);

所以如果想取到全部的参数可以:

//1,对应相同数量的参数
function tag(x,y,z){
    return x,y,z    // y = 1 , z = 3
}
//2,使用reset参数
function tag(x , ...y){
    return x,y;    //x = ['this is' , 'and' , ""] y = [1,3]
}
//3,arugments
function tag(x){
    return arguments;    //0:['this is' , 'and' , ''] 1:1 2:3
}

 

按照调用的语句拼接:

function tag(x,...y){
    let output = '';
    y.forEach((item,index)=>{
       output += x[index] + item;
    })
    output += x[y.length];
    return output;    // this is 1 and 3
}

常见用法:防止用户恶意插入代码进行XSS攻击,场景:(借鉴自https://blog.csdn.net/qq_43287488/article/details/82873336

1、攻击者通过评论表单提交将<script>alert(‘aaa’)</script>提交到网站

2、网站后端对提交的评论数据不做任何操作,直接存储到数据库中

3、其他用户访问正常访问网站,并且需要请求网站的评论数据

4、网站后端会从数据库中取出数据,直接返回给用户

5、用户得到页面后,直接运行攻击者提交的代码<script>alert(‘aaa’)</script>,所有用户都会在网页中弹出aaa的弹窗

应用:

function safeHTML(templateData,...reset){
    let s = templateData[0]; 
    reset.foreach((item,index)=>{
       let arg = String(item);
       s += arg.replace(/&/g,"&amp;")    //将&转换为字符串&amg
               .replace(/</g,"&lt;")     //将<转换为字符串&lt;
               .replace(/>/g,"&gt;");    //将>转换为&gt;
       s += templateData[index];            
    })
    return s;    //返回转义后的字符串
}
let sender = '<script>alert("abc") < /script>'; // 用户输入的恶意代码
let message = SaferHTML`<p>${sender} has sent you a message.</p>`;
// message -> <p>&lt;script&gt;alert("abc") &lt; /script&gt;<p>

标签函数与模板编译结合,参照官网例子:

// 下面的hashTemplate函数
// 是一个自定义的模板处理函数
let libraryHtml = hashTemplate`
  <ul>
    #for book in ${myBooks}
      <li><i>#{book.title}</i> by #{book.author}</li>
    #end
  </ul>
`;

按照自己想法处理了一下,主要原理参照模板编译,正则替换为JavaScript表达式进行解析:

   let myBooks = [{
        title: "ES6",
        author: "Javascript"
    }];
    let libraryHtml = hashTemplate `
  <ul>
    #for book of ${myBooks}
      <li><i>#{book.title}</i>  by  #{book.author}</li>
    #end
  </ul>
`;
function hashTemplate(template, ...reset) {
        let output = '';
        //正则表达式转换
        let delbrackets = /<(.+?)>/g ,    //()中的内容
         delbraces = /#{(.+?)}/g ,        //{}中的内容
        changefor = /#for/g,              //#for的更改
         changeend = /#end/g;             //#end的替换
        template.forEach((element, index) => {
            //用三元判断拼接的顺序
            index > 0 ? output += element : output += element + 'myBooks){';
        });
        //使用replace进行替换,by字符串实属无奈,学艺不精
        output = output
                .replace(delbrackets, 'echo(`<$1>`) \n')
                .replace(delbraces, '\n echo($1)\n')
                .replace(changefor, 'for(')
                .replace(changeend, '}')
                .replace(/(by)/g, ' echo(`$1`)  ');
        let script =
            `
           (function parse(myBooks){
                let html = '';
                function echo(str){
                    html+=str;
                }
                ${output}
                return html;
           })
        `
        let parse = eval(script);
        document.querySelector('div').innerHTML = parse(...reset);
}

该方法类似于模板编译实例的解法,更改完输出的字符串为:

(function parse(myBooks) {
    let html = '';
    function echo(str) {
        html += str;
    }
    echo(`<ul>`)
    for (book of myBooks) {
        echo(`<li>`)
        echo(`<i>`)
        echo(book.title)
        echo(`</i>`)
        echo(`by`)
        echo(book.author)
        echo(`</li>`)
    }
    echo(`</ul>`)
    return html;
})

String.raw()

用来充当模板字符串的处理函数,返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串。

String.raw`Hi\n${2+3}!`;
// 返回 "Hi\\n5!"

String.raw`Hi\u000A!`;
// 返回 "Hi\\u000A!"

正则的扩展(暂时跳过)


数值的扩展

新增方法:

  1. Number.isFinite() 用来检查一个数值是否为有限的(finite)
  2. Number.isNaN()用来检查一个值是否为NaN。
  3. 而这两个新方法只对数值有效,Number.isFinite()对于非数值一律返回false, Number.isNaN()只有对于NaN才返回true,非NaN一律返回false。

  4. ES6 将全局方法parseInt()和parseFloat(),移植到Number对象上面,Number.parseInft(),Number.parseFloat()。

  5. Number.isInteger()用来判断一个数值是否为整数,如果数值的精度超过这个限度,第54位及后面的位就会被丢弃,这种情况下,Number.isInteger可能会误判。

  6. 如果对数据精度的要求较高,不建议使用Number.isInteger()判断一个数值是否为整数。

  7. Number.EPSILON,JavaScript 能够表示的最小精度,实质是一个可以接受的最小误差范围。

  8. Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。

  9. Number.isSafeInteger()则是用来判断一个整数是否落在这个范围之内。


Math对象的拓展

ES6 在 Math 对象上新增了 17 个与数学相关的方法。所有这些方法都是静态方法,只能在 Math 对象上调用。

  1. Math.trunc方法用于去除一个数的小数部分,返回整数部分,对于非数值,Math.trunc内部使用Number方法将其先转为数值,对于空值和无法截取整数的值,返回NaN。

  2. Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值,如果参数是非数值,会自动转为数值。对于那些无法转为数值的值,会返回NaN。

  3. 返回五种值:

    参数为正数,返回+1;
    参数为负数,返回-1;
    参数为 0,返回0;
    参数为-0,返回-0;
    其他值,返回NaN。

     

  4. Math.cbrt()方法用于计算一个数的立方根,对于非数值,先使用Number方法将其转为数值。

  5. Math.clz32()方法将参数转为 32 位无符号整数的形式,然后这个 32 位值里面有多少个前导 0,对于空值或其他类型的值,Math.clz32方法会将它们先转为数值,然后再计算。

  6. Math.imul()方法返回两个数以 32 位带符号整数形式相乘的结果,返回的也是一个 32 位的带符号整数。

  7. Math.fround()方法返回一个数的32位单精度浮点数形式,主要作用,是将64位双精度浮点数转为32位单精度浮点数,对于 NaN 和 Infinity,此方法返回原值。对于其它类型的非数值,Math.fround 方法会先将其转为数值,再返回单精度浮点数。

  8. Math.hypot()方法返回所有参数的平方和的平方根,如果参数不是数值,Math.hypot方法会将其转为数值。只要有一个参数无法转为数值,就会返回 NaN。

对数方法

  • Math.expm1(x)返回 ex - 1,即Math.exp(x) - 1
  • Math.log1p(x)方法返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN
  • Math.log10(x)返回以 10 为底的x的对数。如果x小于 0,则返回 NaN。
  • Math.log2(x)返回以 2 为底的x的对数。如果x小于 0,则返回 NaN。

双曲函数方法

ES6 新增了 6 个双曲函数方法。

  • Math.sinh(x) 返回x的双曲正弦(hyperbolic sine)
  • Math.cosh(x) 返回x的双曲余弦(hyperbolic cosine)
  • Math.tanh(x) 返回x的双曲正切(hyperbolic tangent)
  • Math.asinh(x) 返回x的反双曲正弦(inverse hyperbolic sine)
  • Math.acosh(x) 返回x的反双曲余弦(inverse hyperbolic cosine)
  • Math.atanh(x) 返回x的反双曲正切(inverse hyperbolic tangent)

ES2016 新增了一个指数运算符(**),特点是右结合,而不是常见的左结合。多个指数运算符连用时,是从最右边开始计算的。

2 ** 2 // 4
2 ** 3 // 8
// 相当于 2 ** (3 ** 2)
2 ** 3 ** 2
// 512

指数运算符可以与等号结合,形成一个新的赋值运算符(**=)。

let a = 1.5;
a **= 2;
// 等同于 a = a * a;

let b = 4;
b **= 3;
// 等同于 b = b * b * b;

 

おすすめ

転載: blog.csdn.net/weixin_41564885/article/details/87928846
おすすめ