with关键字+正则 实现ejs模版

本文探讨了with关键字在JavaScript中的作用,它能简化对同一对象多个属性的引用。通过一个例子展示了with如何影响对象属性的访问,包括在对象不存在属性时可能创建全局变量的副作用。文章提到这个特性在《你不知道的JavaScript》中有详细阐述,并指出可以结合正则表达式来实现EJS模板的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

with关键字通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身 比如

	var obj = {
		a:1,
		b:2,
		c:3
	}
	//单调乏味的重复“obj”
	obj.a = 2;
	obj.b = 3;
	obj.c = 4;
	//简单的快捷方式
	with(obj){
	   a=3;
	   b=4;
	   c=5;
	}

但这实际上并不仅仅是为了方便访问对象的属性,考虑如下代码:

function foo(){
	with(obj){	
		a =2;
	}
};

var o1 = {
	a:3
};

var o2 = {
	b:3
}
foo(o1);
console.log(o1.a)//2 

foo(o2);
console.log(o2.a)// undefined
console.log(a) //2  不好,a被泄露到全局作用域上了

这个例子中创建了o1和o2 两个对象。其中一个具有a属性,另外一个没有。foo(…)函数接受一个obj参数。该参数是一个对象的引用,并对这个对象执行了 with(obj){…} 。我们的代码看起来只是对变量a 进行简单的词法引用,实际上就是一个LHS 引用,并将2赋值给他。

当我们将o1传进去, a =2 赋值操作找到了o1.a 并将2 赋值给他。 而当o2传进去他并没有a属性,因此不会创建这个属性, o2.a保持undefined但是可以看到一个奇怪的现象就是,实际上a=2的赋值操作创建了一个全局的变量a;
这是with的一些坑 还有一些性能上特性 可以参考《你不知道的jacascript》中第二章部分的详述。
我们这里利用with的这一语法特性 配合正则来实现ejs模版的功能

let str = `
<%if(user){%>
   hello <%=user.name%>
<%}else{%>
   hello guest
<%}%>
<ul>
<%for(let i=0;i<total;i++){%>
  <li><%=i%></li>
<%}%>
</ul>
`;
//它的原理就是拼出一段函数体代码,然后把options做为作用域变量提供属性
let options = { user: { name: 'test' }, total: 10 };
function render(str, options, callback) {
    let head = "let template = ``;\nwith (options) {\n template+=`";
    str = str.replace(/<%=([\s\S]+?)%>/g, function () {
        return "${" + arguments[1] + "}";
    });
    str = str.replace(/<%([\s\S]+?)%>/g, function () {
        return "`;\n" + arguments[1] + "\n;template+=`";
    });
    let tail = "`}\n return template; ";
    let html = head + str + tail;
    let fn = new Function('options', html);
    let result = fn(options);
    return result;
}
let result = render(str, options);//hello test
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值