ECMAScript 6的一些注意点 第一部分

 

什么是"暂时性死区"?

在代码块内,使用let命令声明变量之前,该变量都是不可用的。

var tmp = 123;
let tmp;    //报错

typeof a;   //报错
let a = 1;

// 不报错
var x = x;
// 报错
let x = x;
// ReferenceError: x is not defined

如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

块级作用域

1、外层作用域无法读取内层作用域的变量。

{
   
   {
   
   {
   
   {
  {let insane = 'Hello World'}
  console.log(insane); // 报错
}}}};

2、避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

// 函数声明语句
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 函数表达式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}

3、ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

// 不报错
'use strict';
if (true) {
  function f() {}
}

// 报错
'use strict';
if (true)
  function f() {}

const

1、只在声明所在的块级作用域内有效。

if (true) {
  const MAX = 5;
}

MAX // Uncaught ReferenceError: MAX is not defined

2、一旦声明,常量的值就不能改变。

3、只声明不赋值,就会报错。

4、同样存在暂时性死区,只能在声明的位置后面使用。

5、const只能保证指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,不能完全控制。

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

const a = [];
a.push('Hello'); // 可执行
a.length = 0;    // 可执行
a = ['Dave'];    // 报错

数组解构

  1. 如果等号右边不是可遍历结构,那么将会报错。
  2. 只要某种数据结构存在Iterator接口,都可以进行解构,Set,生产函数等。
let [a] = 1;
let [a] = false;
let [a] = NaN;
let [a] = undefined;
let [a] = null;
let [a] = {}

对象解构

  1. 变量必须与属相同名
  2. 如果不同名:(真正被赋值的是后者,而不是前者。)
let {foo:baz} = {foo:"aaa" , bar:"bbb"};
baz // "aaa"

如果要将一个已经声明的变量用于解构赋值,请不要将花括号放在行首:

let x ;
({x} = {x:1});

可以方便的将现有对象的方法赋值到某个变量上:

//简化console.log
const {log} = console;
log('简化log')
//Math
let {sin} = Math;

字符串解构

字符串解构时被转换成了一个类似数组的对象,可以读取length属性


字符串拓展

3个查询是否包含字符串的新方法:

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
  • 它们都支持第二个参数,表示开始搜索的位置。

让字符串重复n次:

  • xxx.repeat(n),返回一个新的字符串,参数是 0 到-1 之间的小数,则等同于 0,0 到-1 之间的小数,取整以后等于-0,参数NaN等同于 0。

ES2017引入了补全字符串长度功能,如果某个字符串不够指定长度,会在头部或者尾部补全

  • padStrat() , 用于头部补全,常见用途:为数值补全位数,另一个用途是提示字符串格式
  • '12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
    '09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
  • padEnd() , 用于尾部补全
  • 一共接受两个参数,第一个参数补全生效的最大长度,第二个参数是用来补全的字符串
  • 如果原字符串的长度,等于或者大于最大长度,补全不生效,返回源字符串。
  • 如果用来不全的字符串与原字符串长度和超出最大长度,则截去超出位数后的补全字符串。
  • 省略第二参数,空格自动补充。

返回正则表达式在当前字符串的所有匹配:

matchAll();


模板字符串 -- 编译模板详解

首先需要了解一些知识(正则):

  • ( ) 标记一个子表达式的开始和结束位置,子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。

  • .  匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。

  • ? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。

  • + 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。

  • \ s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。

  • \S  匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。

  • replace中的$1代表什么? $1是正则里的捕获,就是前面的(.*?)里的东西

  • eval()是什么? eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码

自己写的简化版例子:

全部代码:

 let template = `
            <p>
                <@ name @>
            </p>
    `;
    function complate(template){
    let reg = /<@(.+?)@>/g;
    template = template.replace(reg,'`) \n javas($1) \n  javas(`');
    template = 'javas(`' + template + '`)';
    let script = `
    (function parse(name){
            var output = '';
            function javas(html){
                output+=html;
            }
            ${template};
            return output;
    })    
    `
    return script;
}
let parse = eval(complate(template));
document.querySelector('div').innerHTML = parse('DEMO1')

解析:

//首先 有这样一个自定义模板
let template = `
<p> <@name@></p>`;

如果想把它转化为可解析的模板,需要将其转化为JavaScript表达式字符串,如下:

javas(`<p>`) 
javas( name ) 
javas(`</p>`)

步骤:

//首先 需要使用字符串的replace方法,通过正则更改<@@>
let reg = /<@(.+?)@>/g;
template = template.replace(reg,'`) \n javas($1) \n javas(`');

得到结果:


<p>`) 
javas( name ) 
javas(`</p>

可以看到拼接并不完全,接下来:

template = 'javas(`' + template + '`)';
//拼接完即可拿到:
/*
javas(`<p>`) 
javas( name ) 
javas(`</p>`)
*/

拼接完成以后,需要将template放在一个函数中返回:

let script = `
(function parse(name){
    let output = '';
    function javas(html){
        output+=html;
    }
    ${template};
    return output;
})
`;

至此已完成大半,下面将其封装成函数:

function complate(template){
    let reg = /<@(.+?)@>/g;
    template = template.replace(reg,'`) \n javas($1) \n  javas(`')
    template = 'javas(`' + template + '`)';
    let script = `
    (function parse(name){
            var output = '';
            function javas(html){
                    output+=html;
            }
            ${template};
            return output;
    })    
    `
    return script;
}

最后调用:

let parse = eval(complate(template)); //调用return的script模板字符串
document.querySelector('div').innerHTML = parse('DEMO1');    //传入name值渲染到div

输出一下script看起来更直观:

(function parse(name){
     var output = '';
     function javas(html){
        output+=html;
     }
     javas(`<p>`) 
     javas( name ) 
     javas(`</p>`);
     return output;
})    

可以看到这里进行的操作:

  • 定义parse方法用来传入name和调用,定义javas方法,传入参数即为模板字符串和变量,拼接到空字符串上返回,这样就可以得到正常的html结构,最后通过eval()执行函数

output的输出:


            <p>
               DEMO1
            </p>
    

おすすめ

転載: blog.csdn.net/weixin_41564885/article/details/87914732