Structure-study-es6(模板引擎、ES6-Class、装饰器)

417 阅读2分钟

模板引擎

实现模板引擎的原理:正则拼接with语法new Function

    let fs = require("fs");
    let template = fs.readFileSync("./template.html", "utf8");
    // 实现模板引擎的原理  正则
    
    function render(templateStr, obj) {
      // {{name}}
      let head = 'let str = "";\r\n';
      head += "with(xxx){\r\n";
      let content = "str += `";  
      // 取值 {{item}} 这样的取值
      templateStr = templateStr.replace(/\{\{(.+?)\}\}/g, function() {
        return "${" + arguments[1] + "}";
      });
     // 解析语法 把{%和%}去掉
      content += templateStr.replace(/\{\%(.+?)\%\}/g, function() {
        return "`\r\n" + arguments[1] + "\r\nstr+=`";
      });
      let tail = "`\r\n}\r\n return str;";
      // 产生函数
      let fn = new Function("xxx", head + content + tail);
      return fn(obj);
      // return templateStr.replace(/\{\{(.+?)\}\}/g,function(){
      //     return obj[arguments[1]]
      // });
    }
    let r = render(template, { arr: [1, 2, 3] });
    console.log(r);
    
    // template.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        {%arr.forEach(item=>{%}
            <li>{{item}}</li>
        {%})%}
    </body>
    </html>

ES6-Class

ES6-Class 的实现 主要是 通过call + Object.create() + Object.setPrototypeOf实现继承。 通过Object.defineProperty实现了 原型 + 静态方法属性的定义

    class Animal {
        type = '哺乳类'; // 声明到实例上的
        constructor(){
            this.type = '哺乳类'
        }
        get a(){ // Object.defineProperty(Animal.protoype,a)
            return 1; // Animal.prototype.a = 1;
        }
        say(){ // 放到了原型上 // Animal.prototype.say
            console.log(this);
        }
        // 静态属性就是定义到类上的属性 es6中只有静态方法
        static get flag(){ // es6的静态属性
            return  '动物'
        }
    }

如果将类中的方法拿出来用必须绑定this 否则默认指向undefind

    let animal = new Animal(); 
    console.log(Animal.flag)
    let say = animal.say.bind(animal)
    say();

注意事项

    class Animal{
        static flag = 1;
        constructor(name){
            this.name = name;
            this.type = '哺乳类'
        }
        say(){
            console.log('say')
        }
    }
    class Tiger extends Animal{
        constructor(name){
           super(name); // 调用super Animal.call(tiger,name);
            // super 指代的是父类
            // constructor中的super指代的问题
            console.log(this)
        }
        static getAnimal(){
            console.log(super.flag,'---'); // 这个super指代的是父类
        }
        say(){
            super.say(); // super 指向的是 父类的原型
        }
    }
    let tiger = new Tiger('老虎');
    tiger.say()

装饰器

  • 必须是一个函数,只能修饰类。且返回的函数的第一个参数为装饰的类.
  • 对类中的属性 还有类中的方法装饰。返回的函数的参数分别为类的原型, 装饰的keykey对应的属性描述器
    @type1('type1')
    @type3
    class Circle{
        @readonly PI = 3.14;
        @before
        say(){
            console.log('say')
        }
    }
    // 装饰器传递参数 需要再返回一个函数
    function type1(type1){
        // Constructor 为装饰的类
        return function(Constructor){
            Constructor.type1 = type1
        }
    }
    // 不传递参数
    function type3(Constructor){
        Constructor.type3 = 'type3'
    }
    // 对类中的属性装饰
    function readonly(CirclePrototype,key,descriptor){
        descriptor.writable = false;
        descriptor.enumerable = false;
    }
    // 对类中的方法装饰
    function before(CirclePrototype,key,descriptor){
        let oldSay = descriptor.value; // 函数劫持
        descriptor.value = function(){ // 将函数原有的逻辑 进行包装
            console.log('before')
            oldSay()
        }
    }
    let c = new Circle();
    c.say();