位置: 编程技术 - 正文

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

  • 无偿使用场地涉及的问题
  • 返利销售增值税
  • 免税店含增值税吗
  • 手撕汽车票在哪里弄到
  • 境外投资子公司审计报告人民币汇率
  • 行政单位库存材料包括哪些
  • 分公司怎么做
  • 融资担保公司会计建议有哪些要求
  • 车辆购置附加税证丢了能过户吗
  • 人工材料成本怎么分配
  • 进口商品不提供发票合法吗
  • 税前扣除的职工教育经费
  • 海关进口增值税专用缴款书图片
  • 增值税普通发票税率
  • 固定资产报废处置账务处理
  • 公司间借款计入什么科目
  • 劳务费个人还需要交税吗
  • 旅客运输抵税
  • 销售劳务的税率是多少
  • 增资印花税税目
  • 财务报表包含哪些表
  • 个人所得税做账怎么做
  • 计提的存货跌价准备
  • 收到租金税率
  • 鸿蒙os程序
  • 可转换债券具有债权和股权双重特征
  • 无法登陆wifi怎么登陆路由器
  • 拍卖本人文字作品原稿
  • 企业补充养老保险
  • 处置抵债资产的增值税计入
  • ssms注释
  • js编写一个标准的单例模式类
  • 马德拉群岛旅游攻略
  • 企业所得税如何更正申报
  • 印刷厂成本核算
  • 南极岛在哪
  • 如何向企业账户转钱
  • css 100vw、100vh出现滚动条怎么解决
  • 报废机器设备如何缴纳增值税
  • phpcms v9官网
  • 公司年夜饭怎么说话
  • 帝国cms教程官方完整版
  • 银行不良资产核销后怎么处理
  • 帝国cms批量添加文章
  • mongodb的配置文件
  • 长期待摊费用计提摊销的会计分录
  • 库存现金的主要内容有哪些
  • 补充登记法是全部都用蓝字吗
  • 物业费的会计处理
  • 成本类科目在哪里列式
  • 其他应付款能否直接做实收资本的账务处理
  • 提取银行存款利息分录
  • 超期应收款管控
  • 机票的电子发票可以报销吗
  • 当月发票未到怎么做账
  • 资产处置损益在资产负债表哪里
  • 记账凭证先写借方还是贷方
  • 忘记MySQL的root密码该怎么办
  • sql语句实例大全
  • sql判断是否存在记录
  • svchost一直在下载什么
  • win10预览版好用吗
  • 任务栏taskbar 教程
  • 破解ssh端口
  • 怎么查看win7系统电脑访问了哪些应用程序
  • 挖掘出潜能
  • linux分割分区
  • 微软称十年内将淘汰程序员
  • win7在开始菜单右击
  • win系统开发
  • vps可以安装虚拟机吗
  • windows向microsoft报告
  • linux常见的启动方式
  • jQuery+Ajax实现无刷新分页
  • Protecting Content With AssetBundle[Unity]
  • android 标签页
  • 重庆国税电子税务局
  • 苏州税务中心
  • 吉林税务发票自动查询系统网
  • 成品油消费税税率表
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设