续[AS3]E4X的变量展开详解(1)——基础,下面来研究E4X变量展开的内部实现。
源文件:
var a = <a>abc{123}def</a>;
使用 abcdump 反编译后的结果:
0 getlocal0
1 pushscope
2 findpropstrict XML
4 getproperty XML
6 pushstring "<a>abc"
8 pushbyte 123
10 esc_xelem
11 add
12 pushstring "def</a>"
14 add
15 construct (1)
17 getglobalscope
18 swap
19 setslot 1
21 returnvoid
与 new String()
做比较
源文件:
var a = new String("a")
使用 abcdump 反编译后的结果:
0 getlocal0
1 pushscope
2 findpropstrict String
4 pushstring "a"
6 constructprop String (1)
9 getglobalscope
10 swap
11 setslot 1
13 returnvoid
会发现 E4X 与 new String()
很相似。
先来看压栈的部分
new String()
的为:
4 pushstring "a"
6 constructprop String (1)
new String()
是先把 "a"
压入堆栈,再调用构造函数。
而 E4X 的为:
6 pushstring "<a>abc"
8 pushbyte 123
10 esc_xelem
11 add
12 pushstring "def</a>"
14 add
15 construct (1)
有点复杂,过程为:
1.把 "<a>abc"
压入堆栈(第6行)
"<a>abc" |
XML |
2.把 123
压入堆栈(第8行)
123
|
"<a>abc" |
XML
|
3.把 栈顶(这里为 123
)转换为 String
。(第10行) esc_xelem 相当于 toXMLString(123)
*注意 toXMLString
为内部函数,无法调用。
"123"
|
"<a>abc" |
XML
|
4.把堆栈的栈顶的两项相加。(第11行)
"<a>abc123" |
XML
|
5.把 "def</a>"
压入堆栈(第12行)
"def</a>"
|
"<a>abc123" |
XML
|
6.把堆栈的栈顶的两项相加。(第14行)
"<a>abc123def</a>" |
XML
|
7.调用构造函数。(第15行)即返回 new XML("<a>abc123def</a>")
。
总结
<a>abc{123}def</a>;
就相当于
new XML("<a>abc" + toXMLString(123) + "def</a>");
最后,关于AVM2的格式可以参照AVM2 Instructions,不明白的语句可以去查一查。
未完待续,下一篇详解效率与实用性。
没有评论:
发表评论