位置: 编程技术 - 正文

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

  • 增值税需要年度报税吗
  • 企业所得税属于地方税吗
  • 税金及附加都包含什么
  • 个税app抵扣多少钱怎么查询
  • 小规模个体户营业执照一共几个章
  • 收到厂家给医药的短信
  • 长期股权投资成本法转权益法追溯调整
  • 转租收入怎样缴税
  • 流动资产周转次数低说明什么
  • 公司债权转让如何处理
  • 小规模纳税人是简易计税吗
  • 车船使用税是否必须交
  • 来料加工贸易是什么工作
  • 长期股权投资的投资收益怎么算
  • 研发费用界定标准
  • 购买车辆保险怎么入账
  • 生产型企业进口退税政策
  • win7不能进系统怎么办
  • 其他流动负债有利息吗
  • 服务业缴税
  • 购买电子承兑差额怎么算
  • 股权转让的条件和方式
  • 带息应收票据的核算
  • 增值税发票红字信息表
  • ios 的 safari 浏览器
  • 企业发生的诉讼费用
  • 转租会计如何记账
  • php和js 哪个简单
  • zendframework3中文手册
  • php截取文件后缀名方法
  • 增值税业务发生的时间
  • 工资必须走银行卡吗
  • javaweb会话跟踪技术有哪些
  • 前端项目性能优势怎么写
  • vue前端常见面试题
  • 付临时工工资需要什么材料
  • 利息收入包括
  • 买配件组装成产品算生产吗
  • 事业单位营业执照
  • 职工教育经费年底要冲回吗
  • 什么情况可以行政拘留不予执行
  • 对公账户的种类有几种
  • 大华摄像头海康威视录像机
  • 商品流通企业购入的商品采用售价金额法核算的
  • 电子发票开出后如何查看
  • 小额贷款公司如何做账
  • 通讯补贴计入个税吗
  • 企业长期股权投资增加说明什么
  • 专利年费可以计入研发费用加计扣除吗
  • 周转材料期末余额怎么算
  • 餐厅的租金是多少钱一个月
  • 增值税专用发票丢了怎么补救
  • 保险的理解
  • 交易性金融资产的入账价值
  • 固定资产净值怎么算
  • 净资产是什么意思举例说明
  • mysql开源社区
  • 数据库访问机制
  • mysql中的rand函数
  • centos7修改网络
  • 用u盘怎么装系统win10
  • libegl.dll病毒
  • 显示隐藏文件也看不到
  • win10链接手机怎么用
  • 修改注册表优化Win10
  • w10开机欢迎界面设置
  • Win10 Mobile 10586正式版即将向Insider用户推送
  • cocos2dx quick lua 学习笔记1
  • node js php
  • easyui原理
  • 在一个android创建一个按钮多选对话框
  • 接口回调java
  • diy相册设计
  • java urlencode如何使用
  • 工程项目管理费计入什么科目
  • 增值税报表进项税和销项税都不填可以吗
  • 按时交纳党费
  • 深圳国税地税怎么申报
  • 漯河经济开发区税务局电话
  • 房产税交错了能否退款
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设