模板引擎
实现模板引擎的原理:
正则拼接、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()
装饰器
- 必须是一个函数,只能修饰类。且返回的函数的第一个参数为
装饰的类. - 对类中的属性 还有类中的方法装饰。返回的函数的参数分别为
类的原型,装饰的key和key对应的属性描述器
@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();