如何在with语句内部函数中使用注入作用域并获取$self变量
问题分析与解决方案
原代码问题
原代码中,$sys.comp的getter函数无法访问with语句中注入的$self,核心原因是函数的作用域由定义时的词法环境决定,而非调用时的环境。getter定义在全局作用域,它的作用域链里不包含with注入的变量环境,因此查找$self时会报错。
实现方案(不移动Object.defineProperty)
要让getter访问到with中的$self,可以利用eval的动态作用域特性——eval会在当前执行上下文(即with的作用域)中查找变量:
const $sys = {}; Object.defineProperty($sys, 'comp', { get: function() { // 使用eval在当前执行上下文查找$self console.log('====', eval('$self')); } }); with({ $self: 1 }) { console.log($sys.comp); // 输出 ==== 1 }
关于with语句内部函数使用注入作用域的说明
函数在with内部定义:
如果函数直接在with语句块内定义,它的词法作用域会包含with注入的变量环境,自然能访问到注入的变量:with({ $self: 1 }) { function logSelf() { console.log($self); // 直接访问到$self } logSelf(); // 输出 1 }函数在with外部定义:
外部定义的函数无法直接访问with的注入变量,因为词法作用域不包含该环境,此时有两种可行方式:- 使用eval动态查找:如上面的解决方案,利用
eval在调用时的上下文查找变量。 - 显式传递变量:调用函数时将
with中的变量作为参数传入:const $sys = {}; $sys.getSelf = function(self) { console.log('====', self); }; with({ $self: 1 }) { $sys.getSelf($self); // 输出 ==== 1 }
- 使用eval动态查找:如上面的解决方案,利用
注意:
with语句在严格模式下会被禁用,且过度使用可能导致代码可读性下降,实际开发中建议尽量避免使用,改用对象解构或直接属性访问替代。
内容的提问来源于stack exchange,提问作者programmerwy
相关产品推荐
相关产品推荐

