js词法作用域之欺骗词法

如果词法作用域完全由写代码期间函数所声明的位置来定义,怎样才能在运行时来“修改”(欺骗)词法作用域。

有两种机制来实现这个目的,但最好不要使用,欺骗词法作用域会导致性能下降。

1. eval
eval函数可以接受一个字符串为参数,并将其中的内容视为好像在书写时就存在于程序中这个位置的代码。
function foo(str,a){
	eval(str);//欺骗
	console.log(a,b);
}
var b=2;
foo("var b=3;",1);//1,3

在严格模式的程序中,eval()在运行时有其自己的词法作用域,意味着其中的声明无法修改所在的作用域。

function foo(str){
	"use strict";
	eval(str);
	console.log(a);//ReferenceError:a is not defined
}
foo("var a=2;");
2. with
with通常被当作重复引用同一个对象中的多个属性的快捷方式,可以不需要重复引用对象本身。
var obj={
	a:1,
	b:2,
	c:3
}
//单调乏味的重复
obj.a=2;
obj.b=3;
obj.c=4;
//简单的快捷方式
with(obj){
	a=3;
	b=4;
	c=5;
	d=6;//obj中无d,所以在全局作用域上创建d=6.
}

但实际上这不仅仅是为了方便的访问对象属性。

function foo(obj){
	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给with时,with所声明的作用域是o1,而这个作用域中含有一个同o1.a属性相符的标识符。当o2作为作用域时,其中并没有a标识符,因此进行了正常的LHS标识符查找,依次是o2作用域、foo()作用域和全局作用域中都没有找到标识符a,所以当a=2执行时,自动创建了一个全局变量(非严格模式)。如果在foo()作用域中找到了a,就会改变foo()作用域中a的值。

严格模式下with被完全禁止,而保留核心功能的前提下,间接或非安全的使用eval()也被禁止了。

使用其中任何一个机制都将导致代码运行变慢。不要使用它们。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值