位置: 编程技术 - 正文

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绘制图形函数)

  • 增值税为10%的有哪些
  • 逆回购会不会亏本金
  • 个人劳务费怎么交税
  • 党建经费的标准
  • 企业所得税季度申报表A类
  • 建筑综合税率包含企业所得税吗
  • 专票打印偏下可以用吗
  • 转账支票的密码盘
  • 建筑业企业纳税人税率是多少
  • 个人与公司交的税怎么算
  • 公益性捐赠可以结转几个年度
  • 神州优车开具的客运服务费入什么科目?
  • 供应商采购额变动原因有哪些
  • 期末调汇的会计怎么做账
  • 增值税 代销
  • 营改增的真实目的
  • 企业收到待清算的现金
  • 建筑类企业可以申报高新吗
  • 自然人转让股权税收筹划
  • 长期应付款怎么冲减
  • 创新券兑付怎么操作
  • 超市买的日用品没消毒直接用
  • 咨询服务用什么科目
  • 找不到powershell.exe文件
  • win11如何设置定时关机
  • win7怎么更改开机启动项
  • 大理石横切面
  • 失业保险稳岗补贴是什么意思
  • 折扣销售的定义
  • 企业事业单位应当采取有效措施
  • wordpress使用
  • 期间费用核算内容包括
  • 财务费用核算的内容没有
  • uniapp使用高德猎鹰服务
  • php中session什么意思
  • vue项目运行报错
  • php soap wsdl
  • php uniqueid
  • echarts在地图上标记图标
  • utermux命令
  • 医疗保险合同印花税怎么交
  • 项目资金支付
  • 火车头造型
  • mysql自动生成id
  • 实际缴纳的增值税用哪个科目
  • 购入画图软件
  • 企业所得税会计利润总额计算公式
  • 视同小规模纳税人是有?
  • 银行汇票背书
  • 企业哪些账户可以取现金
  • 企业清算所得税申报
  • 银行贷款是应付账款吗
  • 医药发票的税率是多少
  • 农产品收购发票使用范围
  • 专项应付款和政府补助的区别
  • 购入房产会计记账凭证怎么做
  • 收到工程款时会计分录
  • 会计中应收账款属于什么科目
  • 工程项目立项前的安全评估
  • 报销人跟领款人有什么区别
  • 管理费用有负数怎么结总账
  • 事业单位开的发票
  • 年终结账账务处理
  • mysql数据库增量备份命令
  • centos 安装选择
  • jucheck.exe
  • 任务管理器快捷键ctrl+alt+
  • linux mv命令的用法
  • cocos2dx-3.2+lua 启动项目小技巧
  • angular子组件调用父组件的方法
  • android百分比布局
  • 深入理解新发展理念
  • js读取文件大小
  • 个人进口关税税率
  • 发票缴销办理流程图
  • 重庆市国家税务局电子税务局官网
  • 医院网上预约号怎么取消
  • 重庆九龙坡区商务委员会
  • 药店开给个人的增值税发票是什么样
  • 铁路土地使用税减免
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设