浅谈(0,eval)('window')
浅谈(0,eval)('window') vs new Function()
最近研究qiankun 源码,在import-html-entry 包中看到这个,一脸懵,研究了一下,记录一下。参考了这篇博客
这个干啥用的
// 通过这种方式获取全局 window,因为 script 也是在全局作用域下运行的,所以我们通过 window.proxy 绑定时也必须确保绑定到全局 window 上
// 否则在嵌套场景下, window.proxy 设置的是内层应用的 window,而代码其实是在全局作用域运行的,会导致闭包里的 window.proxy 取的是最外层的微应用的 proxy
const globalWindow = (0, eval)('window');
globalWindow.proxy = proxy;
如代码注释所示,这个是确保获取全局作用域的window。
如何做到的
- eval 直接调用与间接调用。es5规范中指明,间接调用eval是在全局作用域中执行。
- 哪些是直接调用,哪些是间接调用。简单来说,计算出eval 值,来调用得就是间接调用,如果是引用就是直接调用。看例子
- 直接调用
eval('...')
(eval)('...')
(((eval)))('...')
(function() { return eval('...') })()
eval('eval("...")')
(function(eval) { return eval('...'); })(eval)
with({ eval: eval }) eval('...')
with(window) eval('...')
- 间接调用
(1, eval)('...')
(eval, eval)('...')
(1 ? eval : 0)('...')
(__ = eval)('...')
var e = eval; e('...')
(function(e) { e('...') })(eval)
(function(e) { return e })(eval)('...')
(function() { arguments[0]('...') })(eval)
this.eval('...')
this['eval']('...')
[eval][0]('...')
eval.call(this, '...')
eval('eval')('...')
- 为什么
,
运算符,会去最后一个运算数,然后取值=,?:
也是如此- 总结来说这些运算符都有一个取值得操作
- 然而
(,)
这两个操作符没有取值这个意味。
聊聊 new Function
- 语法如下,其中所有的参数都是string.参考链接
new Function([arg1,arg2,arg3,...],functionbody)
给个例子
const printme=new Function('message','console.log(message)');
printme('hello world');// 'hello world'
说明几点
- functionbody是在全局作用域中执行的
- 它跟eval 有点类似,只是作用域不一样,eval 是可以访问本地作用域的(前提是直接调用).