- • 参数传递
- • JavaScript调用Flash方法
- • 方法的性能优化
参数传递回目录
当JavaScript调用一个Flash方法的时候,FlashPlayer会将参数转换成XML格式,而转换函数实际上在Flash嵌入到页面并且被正确加载的时候就被抛出到了全局上:
- __flash__argumentsToXML 用于将参数转换成XML表达的方法
- __flash__arrayToXML 用于将数组转换成XML
- __flash__escapeXML 用于将XML内的字符转义
- __flash__objectToXML 用于将Object转换成XML
- __flash__request 用于组成请求体
- __flash__toXML 用于将数据转换成XML
实际上JavaScript 和 Flash 程序之间只能传递字符串数据,任何类型的数据都通过上面的转换函数转换成了xml字符串来表示。假设上面的方法不存在,或者上面的方法被不正确的复写,那么很可能就出现外部JavaScript无法调用到Flash对外注册的接口。
实例如下:
1
2
3
4
5
6
7
8
|
<script type=
"text/javascript"
>
var
myArg = [];
myArg[10000] = 1;
myArg[10001] = {
a : 1,
b :
"string"
};
</script>
|
会被转换成(优化后的):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<
invoke
name
=
"test"
returntype
=
"javascript"
>
<
arguments
>
<
array
>
<
property
id
=
"10000"
>
<
number
>1</
number
>
</
property
>
<
property
id
=
"10001"
>
<
object
>
<
property
id
=
"a"
>
<
number
>1</
number
>
</
property
>
<
property
id
=
"b"
>
<
string
>string</
string
>
</
property
>
</
object
>
</
property
>
</
array
>
</
arguments
>
</
invoke
>
|
JavaScript调用Flash方法回目录
实例如下:
1
2
3
|
<script type=
"text/javascript"
>
alert(testSwf.test);
</script>
|
等同如下:
1
2
3
4
5
6
7
8
|
<script type=
"text/javascript"
>
var
arg = [
'test'
];
for
(
var
i=0; i<arguments.length; ++i)
{
arg.push(arguments[i]);
}
testSwf.CallFunction(__flash__request.apply(
null
, arg));
</script><BR><BR>
|
Flash调用JavaScript方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var
myJavaScript:XML = <script>
<![CDATA[
function
()
{
function
sum(a, b)
{
alert(a + b);
}
sum(
1
,
2
);
}
]]>
</script>
ExternalInterface.call(myJavaScript);
//output 3<BR><BR>
|
甚至还可以注入JavaScript代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
var
myJavaScript:XML = <script>
<![CDATA[
function
()
{
window.sum =
function
(a, b)
{
alert(a + b);
}
sum(
1
,
2
);
}
]]>
</script>
ExternalInterface.call(myJavaScript);<BR><BR>
|
之后就可以执行如下调用:
1
2
3
|
<script type=
"text/javascript"
>
alert(window.sum);
</script>
|
这样甚至能把你的JavaScript代码嵌入到Flash当中,这样做法的优劣暂时不进行讨论。然而Flash不仅仅能在浏览器中调用JavaScript方法或者注入JavaScript代码,在IE甚至能够调用和注入VBScript的方法和代码。
方法的性能优化回目录
之前提到,Flash Player会在SWF成功加载后将6个函数抛到全局上,然而不幸的是,这六个全局函数都不同程度的存在性能问题,其中问题比较严重的函数是:
函数之一:__flash__arrayToXML 负责将数组转换成XML
1
2
3
4
5
6
7
8
9
|
function
__flash__arrayToXML(obj) {
var
s =
"<array>"
;
for
(
var
i=0; i<obj.length; i++) {
s +=
"
<property id=\""
+ i +
"\">"
+
__flash__toXML(obj[i]) +
"</property>"
;
}
return
s+
"</array>"
;
}
|
假设将如下的JavaScript数组转换成XML
1
2
|
var
myArray = [];
myArray[10000] = 1;
|
上面的函数会循环10000次,把所有的数组元素不管存在与否都解析成XML, 这就导致了以下问题:
- 把性能浪费在无用的解析上
- 使得XML请求体无比庞大
- Flash Player拿到XML数据后还要无奈地建立XML DOM并且将刚才的无用数据解析还原
- 对字符串使用了 += 操作,这个操作在IE浏览器的效率非常低
函数之二:__flash__escapeXML 负责将特殊字符转为实体
1
2
3
4
5
6
|
function
__flash__escapeXML(s) {
return
s.replace(/&/g,
"&"
).replace(/</g,
"<"
).replace(/>/g,
">"
).replace(/\
"/g,
"
"
").replace(/'/g, "
'");
}
|
对字符串做了多达4次的replace, 这也消耗了不少性能。
所以对于需要传递大数据量的情况,建议将这两个全局函数复写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
__flash__arrayToXML =
function
(obj)
{
var
s = [
'<array>'
];
var
len = obj.length
for
(
var
i=0; i<len; ++i) {
if
(
typeof
obj[i] !==
'undefined'
)
{
s.push(
[
'
<property id="'
, i,
'">'
,
__flash__toXML(obj[i]),
'</property>'
].join(
''
)
);
}
}
s.push(
'</array>'
);
return
s.join(
""
);
};
__flash__ecapeXML =
function
(s)
{
var
keywords = {
'"'
:
'"'
,
'<'
:
'≶'
,
'>'
:
'>'
,
'\''
:
'''
};
return
s.replace(
new
RegExp(
'([\'\"\<\>])'
,
'g'
),
function
(a, b)
{
var
c = keywords[b];
return
c ? c : a;
}
);
};
|
===========================================================================================
m_flash.CallFunction() 方法需要一个 XML 格式的字符串作为实参.
而这个字符串的格式如下:
<invoke name="functionName" returntype="xml">
<arguments>
... (individual argument values)
</arguments>
</invoke>
节点为 invoke 节点。它具有两个属性:name,指示要调用的函数的名称;以及returntype,总是为 xml。如果函数调用包括参数,则invoke 节点具有一个 arguments 子节点,该节点的子节点是使用单个值格式(下面将予以说明)进行了格式设置的参数值。
下表列出了 ActionScript 类以及用于对该数据类型的值进行编码的 XML 格式:
ActionScript 类/值 | C# 类/值 | 格式 | 注释 |
---|---|---|---|
null | null | <null/> | |
Boolean true | bool true | <true/> | |
Boolean false | bool false | <false/> | |
String | string | <string>字符串值</string> | |
Number、int、uint | single、double、int、uint |
<number>27.5</number> <number>-12</number> | |
Array(元素可以是混合类型) | 允许混合类型元素的集合,如 ArrayList 或 object[] |
<array> <property id="0"> <number>27.5</number> </property> <property id="1"> <string>Hello there!</string> </property> ... </array> | property 节点定义各个元素,而 id 属性为从零开始的数值索引。 |
Object | 含有字符串键和对象值的字典,如具有字符串键的 HashTable |
<object> <property id="name"> <string>John Doe</string> </property> <property id="age"> <string>33</string> </property> ... </object> | property 节点定义各个属性,而 id 属性为属性名称(字符串)。 |
其它内置或自定义的类 |
<null/> or <object></object> | ActionScript 将其它对象编码为 null 或空对象。不管是哪种情况,所有属性值都会丢失。 |