位置: 编程技术 - 正文

javascript SpiderMonkey中的函数序列化如何进行

编辑:rootadmin
在Javascript中,函数可以很容易的被序列化(字符串化),也就是得到函数的源码.但其实这个操作的内部实现(引擎实现)并不是你想象的那么简单.SpiderMonkey中一共使用过两种函数序列化的技术:一种是利用反编译器(decompiler)将函数编译后的字节码反编译成源码字符串,另一种是在将函数编译成字节码之前就把函数源码压缩并存储下来,用到的时候再解压还原. 如何进行函数序列化 在SpiderMonkey中,能将函数序列化的方法或函数有三个:Function.prototype.toString,Function.prototype.toSource,uneval.只有toString方法是标准的,也就是各引擎通用的.但是ES标准中关于Function.prototype.toString方法的规定(ES5 .3.4.2)只有寥寥数语,也就是说,基本没有标准,引擎自己决定该如何实现. 函数序列化的作用 函数序列化最主要的作用应该是利用序列化生成的函数源码来重新定义这个函数. 你也许会想:"我写了这么多年Javascript,怎么没有遇到这种需求".的确,如果是自己的网站,自己完全控制的js文件,不需要以这种打补丁的方式来修改函数,直接修改就可以了.但是如果源文件不是你能控制的了的话,就很有可能要这样做了.比如常用的地方有greasemonkey脚本:你可能需要禁用或修改某个网站中的某个函数.还有就是Firefox扩展:你需要修改Firefox自身的某个函数(可以说Firefox是用JS写的).举个我自己写的Firefox脚本的例子: 这个代码的作用是:在地址栏上回车时,让Firefox在新标签中打开页面,而不是占用当前标签.实现方式就是用toString方法读取到gURLBar.handleCommand函数的源码,然后用正则替换后传给eval,重新定义了这个函数. 为什么不用直接定义的方式,也就是直接重写函数呢: gURLBar.handleCommand = function(){...//将原本的函数更改了一个小地方} 不能这么做的原因是因为我们得考虑兼容性,我们应该尽可能小的更改这个函数的源码.如果这么写的话,Firefox的gURLBar.handleCommand源码一旦发生变化,这个脚本就失效了.比如Firefox3和Firefox4中都有这个函数,但函数内容差别非常大,可是如果用正则替换部分关键字的话,只要这个被替换的这个关键字没有发生变化的话,就不会出现不兼容的现象. 反编译字节码 在SpiderMonkey中,函数在被解析之后会被编译成字节码(bytecode),也就是说,内存中存储着并不是原始的函数源码.SpiderMonkey中存在一个反编译器,它的主要作用就是把函数的字节码反编译成函数源码的形式. 在Firefox以及之前的版本中,SpiderMonkey使用的就是这种方法,如果你使用的是这些版本的Firefox的话,可以尝试下面的代码: 输出和其他的浏览器完全不同: 1.没有意义的原始值字面量在编译的时候会被删除,这个例子中就是"字符串". 你也许会觉得:"貌似没什么问题,反正这些值对于函数的运行来说并没有什么意义".等等,你是不是忘了个东西,表示严格模式的字符串"use strict"怎么办呢? 在不支持严格模式的版本中,比如Firefox3.6,这个"use strict"和其他字符串没什么区别,编译的时候会被删除.在SpiderMonkey实现了严格模式之后,虽然编译的时候同样会忽略掉这个字符串"use strict",但在反编译的时候会进行判断,如果这个函数处于严格模式中,则会在函数体的第一行添加上"use strict",下面是对应的引擎源码. static JSBool 2.注释在编译的时候也会被删除 这个貌似没太大影响,不过有些人愿意利用函数注释来实现多行字符串,这个方法在Firefox 之前的版本中是不可用的. 我 你 他 3.原始值字面量的运算会在编译时进行. 这算是一种优化方式,《高性能JavaScript》提到过: 反编译的弊端 由于新技术的出现(比如严格模式)以及在修改其他相关bug的时候,反编译器这部分的实现经常需要更改,更改就有可能产生新的bug,我自己就亲身遇到过一个bug.大概是在Firefox左右的时候,具体问题记不大清了,反正是关于反编译时小括号是否要保留的问题,大概是这样的: 在反编译时,(a+b)中的小括号被省略了,由于加法结合律从左到右,所以这没关系.但我遇到的bug是这样的: 这就就不行了,a+b+c不等于a+(b+c),比如在a=1,b=2,c="3"的情况下,a+b+c等于"",而a+(b+c)等于"". 关于反编译器,Mozilla工程师Luke Wagner指出,反编译器对他们实现一些新功能的阻碍很大,而且经常会出现一些bug: Not to pile on, but I too have felt an immense drag from the decompiler in the last year. Testing coverage is also poor and any non-trivial change inevitably produces fuzz bugs.The sooner we remove this drag the sooner we start reaping the benefits. In particular,I think now is a much better time to remove it than after doing significant frontend/bytecode hacking for new language features. Brendan Eich也表示,反编译器的确有很多不理想: I have no love for the decompiler, it has been hacked over for years. 存储函数源码 从Firefox之后,SpiderMonkey改成了第二种实现方法,其他浏览器也应该是这样实现的吧.函数序列化得到的字符串完全和源码一致,包括空白符,注释等等.这样的话,大部分问题就应该没有了吧.不过,貌似我又想到个问题.还是关于严格模式的. 比如: 当然,返回的源码中也应该有"use strict",所有浏览器都是这么实现的: 但如果是这样呢: 内部函数B也处于严格模式中,输出B的函数源码应不应该加上"use strict"呢.试验一下: 上面说了,Firefox之前Firefox4之后的版本是通过判断当前函数是否处于严格模式来决定输出不输出"use strict"的,函数B继承了函数A的严格模式,所以会有"use strict". 同时函数源码是缩进严格的,因为在反编译的时候,SpiderMonkey会给反编译出的源码进行格式化,即使之前的源码完全没有缩进也没关系: Firefox之后的版本会不会带有"use strict"呢?因为是直接把函数源码保存下来的,而且函数B中的确没有"use strict"字样.试验结果是:会添加上"use strict",只是缩进有点问题,因为没有格式化这一步了. SpiderMonkey最新版的jsfun.cpp源码中有对应的注释 // 如果一个函数的某个上层函数中拥有"use strict",那么这个函数就继承了上层函数的严格模式. // 我们也会在这个内部函数的函数体内插入"use strict". // 这就确保了,如果这个函数的toString方法的返回值被重新求值时, // 重新生成的函数会和原函数有着相同的语义. 而不同的是,其他浏览器都是不带"use strict"的: 虽然这不会有什么太大影响,但我觉的Firefox的实现是更合理的.

推荐整理分享javascript SpiderMonkey中的函数序列化如何进行,希望有所帮助,仅作参考,欢迎阅读内容。

javascript SpiderMonkey中的函数序列化如何进行

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

php图像生成函数之间的区别分析 新手对php图像生成函数imagecreatetruecolor()和imagecreate()又不解之处,首先来看看官方对这两个函数的解释:resourceimagecreatetruecolor(int$x_size,int$y_size)返回一

javascrpt绑定事件之匿名函数无法解除绑定问题 经常听到有人说,匿名函数绑定事件不好控制啊,无法解除绑定啊等等等等,一直很奇怪谁说的不能解除绑定。下面来实现click事件2次后,自动解除绑

缓动函数requestAnimationFrame 更好的实现浏览器经动画 写缓动函数用到requestAnimationFrame函数,之前了解过一些,但总觉得又不是很了解,所以翻译一篇老外的文章,以便学习分享。requestAnimationFrame是什么?

标签: javascript SpiderMonkey中的函数序列化如何进行

本文链接地址:https://www.jiuchutong.com/biancheng/379158.html 转载请保留说明!

上一篇:javascript中有趣的反柯里化深入分析(javascript可以制作哪些游戏?)

下一篇:php图像生成函数之间的区别分析(php绘制图形函数)

  • 去年多计提的工资今年直接冲掉当期费用,不调增可以吗
  • 采购材料入库会计分录怎么写的
  • 预收货款开票怎么做账
  • 增值税退税比例怎么算
  • 明明申报了为什么显示没有申报
  • 汇算清缴所得税会计分录
  • 冲减以前年度主营业务成本对今年有影响吗
  • 房产开发后自用需要交土地增值税吗
  • 技术转让所得的税收优惠
  • 记载资金的账簿要交印花税吗
  • 非货币性资产交换补价大于25%的会计处理
  • 企业完税凭证入账后怎么办理退税?
  • 税收六项减免
  • 公司房租可以抵多少税
  • 个人缴纳的公积金可以贷款吗
  • 撤销申报增值税流程
  • 大额保险缴费
  • 微软输入法打不出汉字只有拼音
  • win11 zen2
  • win7系统ie浏览器在哪里
  • 事业单位财政拨款是编制吗
  • 无线路由器如何桥接wifi信号
  • 外币账户收到应收账款
  • 外购货物用于职工奖励
  • vue怎么使用本地存储比较好
  • 原始凭证的内容有哪些
  • 解决出现问题的人
  • laravel添加数据
  • 利得是什么举个例子
  • 劳务费发票差额征税
  • 文心一格百度
  • mysql的字符串
  • 超出python用什么
  • 工会经费发放奖励个税处理
  • 增值税纳税申报类型怎么填
  • 起重机属于固定资产中什么设备类型
  • 发票行业税目怎么选
  • 汇票贴现是什么
  • 未收回的货款属于什么会计科目
  • 总账和成本哪个工资高
  • mysql日志文件在哪
  • 无形资产分期付款会计分录?
  • 预缴税款是什么税款
  • 一般纳税人外地预缴税款怎么做分录
  • 技术服务费发票怎么开
  • 销售商品未开票
  • 什么是累计预扣预缴应纳税所得额
  • 施工单位月末都需要结转什么
  • 投资入股行为
  • 公司开收据盖什么章
  • 京东卖家怎么开普通发票
  • pg 正则表达式
  • 计算机二级考试时间2024
  • 注册表修改数据
  • win7组织在哪
  • Windows 7 和 Vista 下使用 Alipay 的解决方法总结
  • ubuntu字体文件
  • linux怎么操作文件
  • win1020h2版好不好
  • mini programes
  • win7系统搜索不到自己家wi-fi
  • win7数据保护
  • win7系统怎么查看隐藏文件夹
  • win10无法启动diagnostic policy service
  • linux开发android好处
  • js 箭头表达式
  • Android游戏开发入门
  • javascript ie
  • javascript实现2048游戏示例
  • unity3d总结
  • 也论主板的扩展性
  • js控制display属性
  • 将光标定位于输入端
  • 键盘搜索的快捷键
  • 手机关卡类游戏
  • 国家税务总局广东省税务局待遇
  • 四川医保卡原始密码是什么意思
  • 北京市印花税减免政策
  • 郑州广电地址
  • 陕西地税局电话号码
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设