<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_On the road</title><subtitle type="text">菜鸟的成长</subtitle><id>http://feed.cnblogs.com/blog/u/51626/rss</id><updated>2010-12-06T07:04:41Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/51626/rss"/><entry><id>http://www.cnblogs.com/sun11086/archive/2010/08/07/1794678.html</id><title type="text">[转]AS3应用程序模块化开发与ApplicationDomain</title><summary type="text">转自:http://shake863.javaeye.com/blog/408396当程序越来越大，我们需要把它拆分成多个swf，在需要的时候动态加载。拆分时应该尽量把不同的类编译进唯一的swf，避免因swf文件增多而使整个程序的文件尺寸增大。按此原则可以拆分出以下两种swf，借助 ApplicationDomain 共享其代码和资源。 模块(Module) 按照程序逻辑，可以拆分出多个&amp;ldqu...</summary><published>2010-08-07T05:49:00Z</published><updated>2010-08-07T05:49:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/08/07/1794678.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/08/07/1794678.html"/><content type="html">&lt;p&gt;转自:&lt;a href="http://shake863.javaeye.com/blog/408396"&gt;http://shake863.javaeye.com/blog/408396&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;当程序越来越大，我们需要把它拆分成多个swf，在需要的时候动态加载。拆分时应该尽量把不同的类编译进唯一的swf，避免因swf文件增多而使整个程序的文件尺寸增大。按此原则可以拆分出以下两种swf，借助 ApplicationDomain 共享其代码和资源。 &lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;strong&gt;模块(Module)&lt;/strong&gt; &lt;br /&gt;按照程序逻辑，可以拆分出多个&amp;ldquo;功能模块&amp;rdquo;，如&amp;ldquo;注册&amp;rdquo;、&amp;ldquo;管理&amp;rdquo;等等；按照游戏或社区类程序的关卡或场景，可以拆分出不同的&amp;ldquo;场景模块&amp;rdquo;。这些模块不是主程序运行必须的，只在需要的时候加载。 &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;运行时共享库(RSL)&lt;/strong&gt; &lt;br /&gt;主场景或者多个模块通用的资源，比如位图、声音、设计好的页面元素等，可作为&amp;ldquo;库&amp;rdquo;在主程序运行前加载。可以整套更换的皮肤(skin)只需先加载一套。 &lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;ApplicationDomain 是存放AS3定义(包括类、方法、接口等)的容器。使用Loader类加载swf时可以通过指定 ApplicationDomain 参数将swf加载到不同的域(Domain)：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div &gt;&lt;span style="color: green;"&gt;var&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;loader&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;Loader&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: green;"&gt;new&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;Loader&lt;/span&gt; &lt;span style="color: olive;"&gt;()&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;var&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;context&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;LoaderContext&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: green;"&gt;new&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;LoaderContext&lt;/span&gt; &lt;span style="color: olive;"&gt;()&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #ffa500;"&gt;/* 加载到子域(模块) */&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;context&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;applicationDomain&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: green;"&gt;new&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;ApplicationDomain&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;ApplicationDomain&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;currentDomain&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #ffa500;"&gt;/* 加载到同域(共享库) */&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;context&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;applicationDomain&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: blue;"&gt;ApplicationDomain&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;currentDomain&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #ffa500;"&gt;/* 加载到新域(独立运行的程序或模块) */&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;context&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;applicationDomain&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: green;"&gt;new&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;ApplicationDomain&lt;/span&gt; &lt;span style="color: olive;"&gt;()&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;loader&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: teal;"&gt;load&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: green;"&gt;new&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;URLRequest&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: red;"&gt;loaded.swf&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;, &lt;/span&gt;&lt;span style="color: blue;"&gt;context&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;/span&gt; &lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;ApplicationDomain使用类似于显示列表(DisplayList)的树形结构。 相对于舞台(Stage) ，可以认为 ApplicationDomain 最根部的是系统域(system domain)，包含 Flash Player 核心类定义。主程序所在的域(以下简称主域)就是它唯一的子域，类似于Stage下的文档类(Document Class)。&lt;br /&gt;　　一个fla文档类里代码：&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div &gt;&lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;stage&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;addChild&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;mySprite&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;addChild&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;myMC&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;addChild&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;myShape&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;/span&gt; &lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;运行后的显示列表：&lt;br /&gt;&lt;img src="http://eidiot.net/wp-content/uploads/2007/06/01.gif" alt="01.gif" /&gt;&lt;br /&gt;　　ApplicationDomain 的类似结构：&lt;br /&gt;&lt;img src="http://eidiot.net/wp-content/uploads/2007/06/02.gif" alt="02.gif" /&gt;&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;strong&gt;加载到子域(模块)&lt;/strong&gt; &lt;br /&gt;类似于&amp;ldquo;继承&amp;rdquo;，子域可以直接获得父域所有的类定义，反之父域得不到子域的。和继承关系不同的是，如果子域中有和父域同名的类，子域定义会被忽略而使用父域的定义。 &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;加载到同域(运行时共享库)&lt;/strong&gt; &lt;br /&gt;类似集合里的合并关系。被加载swf里的所有类定义被合并到当前域中可以直接使用。和加载到子域相同，和当前域同名的定义也会被忽略。 &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;加载到新域(独立运行的程序或模块)&lt;/strong&gt; &lt;br /&gt;swf载入指定域之前，先要检查该域及其父域中是否存在同名类，重复定义一概忽略。如果加载别人写的程序，或者使用旧版本的主程序加载新版本的模块，为避免类名冲突就要加载到新域独立运行以使用自己的类。 &lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;模块加载到同域不是一样可以吗？为何要加载到子域呢？好处就在于，卸载一个加载到子域的模块时，只要确保清除所有到该模块的引用，模块的所有类定义将被垃圾回收(Garbage Collection)。&lt;br /&gt;　　有两种方式可以访问 ApplicationDomain :&lt;/p&gt;&#xD;
&lt;ul&gt;&#xD;
&lt;li&gt;&lt;strong&gt;ApplicationDomain.currentDomain&lt;/strong&gt; &lt;br /&gt;currentDomain是ApplicationDomain的静态变量，表示&lt;strong&gt;当前代码&lt;/strong&gt; 所在的域。该变量很奇特，在主程序里指向主域，在加载到子域的模块里则指向该模块所在的子域。虽然 ApplicationDomain 有个 parentDomain 属性，但子域已经自动获得了父域的类定义，所以通过 ApplicationDomain.currentDomain 就可以获取父域定义了&amp;mdash;&amp;mdash;包括主程序和加载到主域的共享库。(注：系统域不可直接访问，主域和所有新域即系统域子域的parentDomain属性为 null) &lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;LoaderInfo类的applicationDomain属性&lt;/strong&gt; &lt;br /&gt;此方式可以访问任何方式加载的swf的 ApplicationDomain。对于主程序来说，加载到同域的库定义已经存在于 ApplicationDomain.currentDomain ，而模块的类主程序一般用不到。所以这种方式个人不推荐使用。 &lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;ApplicationDomain 的 hasDefinition() 方法判断某定义是否存在，getDefinition() 方法获取指定的定义。下面以一个 &lt;a target="_blank" href="http://eidiot.net/lessons/appdomain/demo/" &gt;例子&lt;/a&gt; 来介绍 ApplicationDomain 的具体用法和应用程序的拆分。&lt;br /&gt;　　&lt;a target="_blank" href="http://eidiot.net/lessons/appdomain/demo/" &gt;本例&lt;/a&gt; 有四个swf，shell.swf是主程序，lib.swf是共享库，login.swf和result.swf分别是&amp;ldquo;登录&amp;rdquo;和&amp;ldquo;结果&amp;rdquo;模块，所有的视图元件都在共享库中。实际开发时可能有很多库，比如&amp;ldquo;位图库&amp;rdquo;、&amp;ldquo;音效库&amp;rdquo;、&amp;ldquo;模型通用库&amp;rdquo;等。&amp;ldquo;通用库&amp;rdquo;里存放多个模块共用的资源，比如此例中的背景元素。而各个模块独有的资源还是放在各自的swf中。&lt;br /&gt;　　主程序首先将共享库加载到同域，完成后将&amp;ldquo;登录模块&amp;rdquo;加载到子域。主程序可以像操作普通的视觉对象(DisplayObject)一样操作加载的模块：监听事件、调用方法。因为编译器不会识别未定义的类，为使用强类型，建议为主类和模型定义相应的接口，使用少量的重复代码协助编程。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div &gt;&lt;span style="color: green;"&gt;private&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;function&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;showModule&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;p_module&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;IModule&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: green;"&gt;void&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;if&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;m_moduleList&lt;/span&gt; &lt;span style="color: olive;"&gt;[&lt;/span&gt; &lt;span style="color: maroon;"&gt;0&lt;/span&gt; &lt;span style="color: olive;"&gt;]&lt;/span&gt; &lt;span style="color: gray;"&gt;== &lt;/span&gt;&lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: red;"&gt;login.swf&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: blue;"&gt;p_module&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: teal;"&gt;show&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: blue;"&gt;p_module&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;addEventListener&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: red;"&gt;login&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: gray;"&gt;, &lt;/span&gt;&lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;onLogin&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;else&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: blue;"&gt;p_module&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: teal;"&gt;show&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;, &lt;/span&gt;&lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;m_userName&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;模块&amp;ldquo;继承&amp;rdquo;了主程序和共享库的所有类和资源，可以通过 ApplicationDomain.currentDomain.getDefinition() 来获取相应的类。注意获取不存在的类会抛出一个 ReferenceError。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div &gt;&lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;function&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;getClass&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;p_name&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: teal;"&gt;String&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;Class&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;try&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;return&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;ApplicationDomain&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;currentDomain&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;getDefinition&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;p_name&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;Class&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;catch&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;p_e&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;ReferenceError&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: teal;"&gt;trace&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: red;"&gt;定义 &lt;/span&gt;&lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: gray;"&gt;+ &lt;/span&gt;&lt;span style="color: blue;"&gt;p_name&lt;/span&gt; &lt;span style="color: gray;"&gt;+ &lt;/span&gt;&lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: red;"&gt;不存在&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;return&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;null&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;return&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;null&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;登录模块获取库中的界面元素，并在点击按钮后抛出事件。Event类不允许带参数，必须使用继承Event的自定义事件抛出参数。主程序可以把模块的自定义事件也编译进去(这样就增大了整个程序的文件尺寸)，或者让监听模块事件的函数接受一个Objcet参数，以获取其动态属性。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div &gt;&lt;span style="color: green;"&gt;private&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;function&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;onLogin&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;p_e&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: teal;"&gt;Object&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: green;"&gt;void&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;m_userName&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: blue;"&gt;p_e&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;userName&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;var&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: teal;"&gt;login&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;IModule&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: blue;"&gt;p_e&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;currentTarget&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: teal;"&gt;login&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;removeEventListener&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: red;"&gt;login&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: gray;"&gt;, &lt;/span&gt;&lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;onLogin&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: teal;"&gt;login&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: teal;"&gt;dispose&lt;/span&gt; &lt;span style="color: olive;"&gt;()&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;loadSwf&lt;/span&gt; &lt;span style="color: olive;"&gt;()&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;主程序收到事件之后卸载注册模块，加载&amp;ldquo;结果模块&amp;rdquo;到子域，并将登录模块传出的&amp;rdquo;userName&amp;rdquo;参数传给结果模块。&lt;/p&gt;&#xD;
&lt;div &gt;&#xD;
&lt;div &gt;&lt;span style="color: green;"&gt;public&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;function&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: teal;"&gt;show&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;p_parent&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;DisplayObjectContainer&lt;/span&gt; &lt;span style="color: gray;"&gt;, ... &lt;/span&gt;&lt;span style="color: blue;"&gt;rest&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: green;"&gt;void&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;var&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;libClass&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;Class&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;getClass&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: red;"&gt;net.eidiot.appDomainDemo.Libaray&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;if&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;libClass&lt;/span&gt; &lt;span style="color: gray;"&gt;!= &lt;/span&gt;&lt;span style="color: green;"&gt;null&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;initUi&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;libClass&lt;/span&gt; &lt;span style="color: gray;"&gt;, &lt;/span&gt;&lt;span style="color: blue;"&gt;rest&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;protected&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;function&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;initUi&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;p_libClass&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: blue;"&gt;Class&lt;/span&gt; &lt;span style="color: gray;"&gt;, &lt;/span&gt;&lt;span style="color: blue;"&gt;p_rest&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: teal;"&gt;Array&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: green;"&gt;null&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: green;"&gt;void&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;{&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;addUi&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;getClass&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;p_libClass&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;BG_NAME&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;, &lt;/span&gt;&lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: red;"&gt;结果&lt;/span&gt; &lt;span style="color: #8b0000;"&gt;"&lt;/span&gt; &lt;span style="color: olive;"&gt;)&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;var&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;resultFunc&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: teal;"&gt;Function&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: blue;"&gt;p_libClass&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: teal;"&gt;getResult&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;var&lt;/span&gt; &lt;span style="color: gray;"&gt;&lt;/span&gt;&lt;span style="color: blue;"&gt;userName&lt;/span&gt; &lt;span style="color: gray;"&gt;: &lt;/span&gt;&lt;span style="color: teal;"&gt;String&lt;/span&gt; &lt;span style="color: gray;"&gt;= &lt;/span&gt;&lt;span style="color: blue;"&gt;p_rest&lt;/span&gt; &lt;span style="color: olive;"&gt;[&lt;/span&gt; &lt;span style="color: maroon;"&gt;0&lt;/span&gt; &lt;span style="color: olive;"&gt;]&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt; &lt;span style="color: green;"&gt;this&lt;/span&gt; &lt;span style="color: gray;"&gt;.&lt;/span&gt; &lt;span style="color: blue;"&gt;addChild&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;resultFunc&lt;/span&gt; &lt;span style="color: olive;"&gt;(&lt;/span&gt; &lt;span style="color: blue;"&gt;userName&lt;/span&gt; &lt;span style="color: olive;"&gt;))&lt;/span&gt; &lt;span style="color: gray;"&gt;;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: olive;"&gt;}&lt;/span&gt; &lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;注意initUi()方法分别使用了共享库中Libaray类的静态属性BG_NAME和静态方法getResult()。但是直接调用此静态方法会报错，可以先用 resultFunc 变量取出此方法。详细内容请参考 &lt;a target="_blank" href="http://eidiot.net/lessons/appdomain/AppDomainDemo.rar" &gt;源代码&lt;/a&gt; 。&lt;/p&gt;&#xD;
&lt;div &gt;&lt;a target="_blank" href="http://eidiot.net/lessons/appdomain/demo" &gt;实例效果演示&lt;/a&gt; &lt;br /&gt;&lt;a target="_blank" href="http://eidiot.net/lessons/appdomain/AppDomainDemo.rar" &gt;下载源文件&lt;/a&gt; (rar 278K) &lt;/div&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1794678.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/08/07/1794678.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/08/04/1792146.html</id><title type="text">[转] JavaScript 基础数据类型</title><summary type="text">JavaScript 有六种数据类型。主要的类型有 number、string、object 以及 Boolean 类型,其他两种类型为 null 和 undefined。　　 String 字符串类型:字符串是用单引号或双引号来说明的。（使用单引号来输入包含引号的字符串。）如：&amp;ldquo;The cow jumped over the moon.&amp;rdquo;数值数据类型：JavaScript...</summary><published>2010-08-04T06:26:00Z</published><updated>2010-08-04T06:26:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/08/04/1792146.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/08/04/1792146.html"/><content type="html">&lt;div  style="text-indent: 24pt; margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; JavaScript 有六种数据类型。主要的类型有&lt;span style="color: #ff0000;"&gt;&lt;strong&gt; number&lt;/strong&gt;&lt;/span&gt;、&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;string&lt;/span&gt;&lt;/strong&gt;、&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;object &lt;/span&gt;&lt;/strong&gt;以及 &lt;span style="color: #ff0000;"&gt;&lt;strong&gt;Boolean &lt;/strong&gt;&lt;/span&gt;类型,其他两种类型为 &lt;span style="color: #ff0000;"&gt;&lt;strong&gt;null &lt;/strong&gt;&lt;/span&gt;和 &lt;span style="color: #ff0000;"&gt;&lt;strong&gt;undefined&lt;/strong&gt;&lt;/span&gt;。&lt;br /&gt;　　 &lt;span style="color: #ff0000;"&gt;&lt;strong&gt;String &lt;/strong&gt;&lt;/span&gt;字符串类型:字符串是用单引号或双引号来说明的。（使用单引号来输入包含引号的字符串。）如：&amp;ldquo;The cow jumped over the moon.&amp;rdquo;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;div  style="text-indent: 24pt; margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;数值数据类型：JavaScript 支持整数和浮点数。整数可以为正数、0 或者负数；浮点数可以包含小数点、也可以包含一个 &amp;ldquo;e&amp;rdquo;（大小写均可，在科学记数法中表示&amp;ldquo;10的幂&amp;rdquo;）、或者同时包含这两项。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;div  style="text-indent: 24pt; margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;Boolean &lt;/strong&gt;&lt;/span&gt;类型：可能的 Boolean 值有 true 和 false。这是两个特殊值，不能用作 1 和 0。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;div  style="text-indent: 24pt; margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;Undefined &lt;/strong&gt;&lt;/span&gt;数据类型：一个为 undefined 的值就是指在变量被创建后，但未给该变量赋值以前所具有的值。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;div  style="text-indent: 24pt; margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;Null &lt;/strong&gt;&lt;/span&gt;数据类型：null 值就是没有任何值，什么也不表示。&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;div  style="text-indent: 24pt; margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;object&lt;/strong&gt;&lt;/span&gt;类型：除了上面提到的各种常用类型外，对象也是JavaScript中的重要组成部分，这部分将在后面章节详细介绍。 &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;　　在 JavaScript 中变量用来存放脚本中的值，这样在需要用这个值的地方就可以用变量来代表，一个变量可以是一个数字，文本或其它一些东西。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;　　 JavaScript是一种对数据类型变量要求不太严格的语言，所以不必声明每一个变量的类型，变量声明尽管不是必须的，但在使用变量之前先进行声明是一种好的习惯。可以使用 var 语句来进行变量声明。如：var men = true; // men 中存储的值为 Boolean 类型。 &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;　　变量命名&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;:JavaScript 是一种区分大小写的语言，因此将一个变量命名为 computer 和将其命名为 Computer是不一样的。&lt;br /&gt;　　另外，变量名称的长度是任意的，但必须遵循以下规则： &lt;br /&gt;　　 1.第一个字符必须是一个字母（大小写均可）、或一个下划线(_)或一个美元符 ($)。 &lt;br /&gt;　　 2.后续的字符可以是字母、数字、下划线或美元符。 &lt;br /&gt;　　 3.变量名称不能是保留字。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;需要注意js里面var，它控制了变量的作用范围。函数内的变量只要带有var，那么函数内用的这个变量就和函数外的无关。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;div id="blog_text" &gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;　　&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;var a；&lt;br /&gt;c=new function(){var a=1;alert(typeof(a));};&lt;br /&gt;alert(typeof(a));&lt;br /&gt;结果为：number，undefined；&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;var a=1；&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: medium;"&gt;&lt;br /&gt;c=new function(){alert(typeof(a));var a=1;};&lt;br /&gt;alert(typeof(a));&lt;br /&gt;结果为：undefined，number；&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;var a；&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: medium;"&gt;&lt;br /&gt;c=new function(){alert(typeof(a));a=1;};&lt;br /&gt;alert(typeof(a));&lt;br /&gt;结果为：undefined，number；&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;var a；&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;c=new function(){var a=1;alert(typeof(a));};可以在c里面用this.a来访问全局变量a&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p  style="margin: auto 0cm;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="font-size: medium;"&gt;============&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&lt;span style="color: #000000;"&gt;&#xD;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;说出它们的值&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1、typeof(NaN) number、typeof(Infinity) number、typeof(null) object、typeof(undefined) undefined&lt;br /&gt;2、NaN == NaN false&lt;br /&gt;3、NaN != NaN true&lt;br /&gt;4、NaN &amp;gt;= NaN false&lt;br /&gt;5、null == undefined true&lt;br /&gt;6、null &amp;gt;= undefined false&lt;br /&gt;7、null &amp;lt;= undefined false&lt;br /&gt;8、parseInt("123abc") 123&lt;br /&gt;9、"123abc" - 0 NaN&lt;br /&gt;10、Infinity &amp;gt; 10 true&lt;br /&gt;11、Infinity &amp;gt; "abc" false&lt;br /&gt;12、Infinity == NaN false&lt;br /&gt;13、true == 1 ture&lt;br /&gt;14、new String("abc") == "abc" true&lt;br /&gt;15、new String("abc") === "abc" false 完全相同&lt;/p&gt;&#xD;
&lt;/span&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;关系运算符&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-size: medium;"&gt;（&amp;lt;、&amp;gt;、&amp;lt;=、&amp;gt;=）&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;ul type="disc"&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;试图将 expression1 和 expression2 都转换为数字。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;如果两表达式均为字符串，则按字典序进行字符串比较。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;如果其中一个表达式为 &lt;/span&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;NaN&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-size: medium;"&gt;，返回 &lt;/span&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;false&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-size: medium;"&gt;。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;负零等于正零。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;负无穷小于包括其本身在内的任何数。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;正无穷大于包括其本身在内的任何数。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;相等运算符&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-size: medium;"&gt; （==、!=）&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;ul type="disc"&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;如果两表达式的类型不同，则试图将它们转换为字符串、数字或 Boolean 量。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;NaN&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-size: medium;"&gt; 与包括其本身在内的任何值都不相等。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;负零等于正零。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;null 与 null 和 undefined 相等。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;相同的字符串、数值上相等的数字、相同的对象、相同的 Boolean 值或者（当类型不同时）能被强制转化为上述情况之一，均被认为是相等的。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;li&gt;&lt;span style="font-size: medium;"&gt;其他比较均被认为是不相等的。 &lt;/span&gt;&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;&lt;strong&gt;&lt;span style="font-size: medium;"&gt;恒等运算符&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-size: medium;"&gt; （===、!==）&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;除了不进行类型转换，并且类型必须相同以外，这些运算符与相等运算符的作用是一样的。&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="font-size: medium;"&gt;&lt;br /&gt;说出它们的输出结果&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;1、&lt;br /&gt;var a = "123abc";&lt;br /&gt;alert(typeof(a++)); string，++运算符在typeof时候没有执行&lt;br /&gt;alert(a); NaN&lt;/p&gt;&#xD;
&lt;p&gt;2、a是string类型&lt;br /&gt;var a = "123abc";&lt;br /&gt;a.valueOf = function(){return parseInt(a);}&lt;br /&gt;alert(++a); NaN&lt;br /&gt;alert(a-0); NaN&lt;/p&gt;&#xD;
&lt;p&gt;3、a是object类型&lt;br /&gt;var a = new Object();&lt;br /&gt;a.toString = function(){return "123abc";}&lt;br /&gt;a.valueOf = function(){return parseInt(a);}&lt;br /&gt;alert(++a);124&lt;br /&gt;alert(a-0);124&lt;/p&gt;&#xD;
&lt;p&gt;4、&lt;br /&gt;String.prototype.valueOf = function()&lt;br /&gt;{&lt;br /&gt;return parseFloat(this);&lt;br /&gt;}&lt;br /&gt;alert("123abc" &amp;gt; 122); false&lt;br /&gt;alert(new String("123abc") &amp;gt; 122); true&lt;/p&gt;&#xD;
&lt;p&gt;5、&lt;br /&gt;var s = new String("abc");&lt;br /&gt;alert(typeof(s) == typeof("abc"));false&lt;br /&gt;alert(s === "abc");false&lt;br /&gt;alert(s.toString() == s);true&lt;/p&gt;&#xD;
&lt;p&gt;6、&lt;br /&gt;var a = new Object();&lt;br /&gt;a.toString = function(){return "a"};&lt;br /&gt;var b = new Object();&lt;br /&gt;b.toString = function(){return "b"};&lt;br /&gt;alert(a&amp;gt;b);&lt;br /&gt;a.valueOf = function(){return 1};&lt;br /&gt;b.valueOf = function(){return 0};&lt;br /&gt;alert(a&amp;gt;b);&lt;/p&gt;&#xD;
&lt;p&gt;7、&lt;br /&gt;function step(a)&lt;br /&gt;{&lt;br /&gt;return function(x)&lt;br /&gt;{&lt;br /&gt;return x + a++;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;var a = step(10);&lt;br /&gt;var b = step(20);&lt;br /&gt;alert(a(10));&lt;br /&gt;alert(b(10));&lt;/p&gt;&#xD;
&lt;/span&gt;&#xD;
&lt;p&gt;from:http://www.javaeye.com/topic/427150&lt;/p&gt;&#xD;
&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1792146.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/08/04/1792146.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/07/16/1779082.html</id><title type="text">随手tip</title><summary type="text">对于存在于同一个元件中的元素,如果有一个对象是"打散"对象构成的动画,那么这个元件中的所有元素都会被flash player重绘</summary><published>2010-07-16T09:16:00Z</published><updated>2010-07-16T09:16:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/07/16/1779082.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/07/16/1779082.html"/><content type="html">&lt;p&gt;对于存在于同一个元件中的元素,如果有一个对象是"打散"对象构成的动画,那么这个元件中的所有元素都会被flash player重绘&lt;/p&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1779082.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/07/16/1779082.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/04/12/1710475.html</id><title type="text">一位软件工程师的7年总结(转)</title><summary type="text">勉励下自己...1、分享第一条经验：&amp;ldquo;学历代表过去、能力代表现在、学习力代表未来。&amp;rdquo;其实这是一个来自国外教育领域的一个研究结果。相信工作过几年、十几年的朋友对这个道理有些体会吧。但我相信这一点也很重要：&amp;ldquo;重要的道理明白太晚将抱憾终生！&amp;rdquo;所以放在每一条，让刚刚毕业的朋友们早点看到哈！2、一定要确定自己的发展方向，并为此目的制定可行的计划。不 要说什么，...</summary><published>2010-04-12T11:15:00Z</published><updated>2010-04-12T11:15:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/04/12/1710475.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/04/12/1710475.html"/><content type="html">&lt;p&gt;勉励下自己...&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;1、分享第一条经验：&amp;ldquo;学历代表过去、能力代表现在、学习力代表未来。&amp;rdquo;&#xD;
其实这是一个来自国外教育领域的一个研究结果。相信工作过几年、十几年的朋友对这个道理有些体会吧。但我相信这一点也很重要：&amp;ldquo;重要的道理明白太晚将抱憾终生！&amp;rdquo;所以放在每一条，让刚刚毕业的朋友们早点看到哈！&lt;/p&gt;&#xD;
&lt;p&gt;2、一定要确定自己的发展方向，并为此目的制定可行的计划。&#xD;
不 要说什么，&amp;ldquo;我刚毕业，还不知道将来可能做什么？&amp;rdquo;，&amp;ldquo;跟着感觉走，先做做看&amp;rdquo;。因为，这样的观点会通过 你的潜意识去暗示你的行为无所事事、碌碌无为。一直做技术，将来成为专家级人物？向管理方向走，成为职业经理人？先熟悉行业和领域，将来自立门户？还是先 在行业里面混混，过几年转行做点别的？这很重要，它将决定你近几年、十年内&amp;ldquo;做什么事情才是在做正确的事情！&amp;rdquo;。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;3、软件开发团队中，技术不是万能的，但没有技术是万万不能的！&#xD;
在 技术型团队中，技术与人品同等重要，当然长相也比较重要哈，尤其在MM比较多的团队中。在软件项目团队 中，技术水平是受人重视和尊重的重要砝码。无论你是做管理、系统分析、设计、编码，还是产品管理、测试、文档、实施、维护，多少你都要有技术基础。算我孤 陋寡闻，我还真没有亲眼看到过一个外行带领一个软件开发团队成功地完成过软件开发项目，哪怕就一个，也没有看到。倒是曾经看到过一个&amp;ldquo;高学历的牛人&amp;rdquo;（非 技术型）带一堆人做完过一个项目，项目交付的第二天，项目组成员扔下一句&amp;ldquo;再也受不了啦！&amp;rdquo;四分五裂、各奔东西。那个项目的&amp;ldquo;成功度&amp;rdquo;大家可想而知了。&lt;/p&gt;&#xD;
&lt;p&gt;4、详细制定自己软件开发专业知识学习计划，并注意及时修正和调整（软件开发技术变化实在太快）。&#xD;
请 牢记：&amp;ldquo;如果一个软件开发人员在1、2年内都没有更新过自己的知识，那么，其实他已经不再属于这个行业了。&amp;rdquo;不要告诉自己没有时间。来自时间管理 领域的著名的&amp;ldquo;三八原则&amp;rdquo;告诫我们：另外的那8小时如何使用 将决定你的人生成败！本人自毕业以来，平均每天实际学习时间超过2小时。&lt;/p&gt;&#xD;
&lt;p&gt;5、书籍是人类进步的阶梯，对软件开发人员尤其如此。&#xD;
书 籍是学习知识的最有效途径，不要过多地指望在工作中能遇到&amp;ldquo;世外高人&amp;rdquo;，并不厌其烦地教你。对于花钱买书，我个人经验是：千万别买国内那帮人出的 书！我买的那些 家伙出的书，100%全部后悔了，无一本例外。更气愤的是，这些书在二手市场的地摊上都很难卖掉。&amp;ldquo;拥有书籍并不表示拥有知识；拥有知识并不表示拥有技 能；拥有技能并不表示拥有文化；拥有文化并不表示拥有智慧。&amp;rdquo;只有将书本变成的自己智慧，才算是真正拥有了它。&lt;/p&gt;&#xD;
&lt;p&gt;6、不要仅局限于对某项 技术的表面使用上，哪怕你只是偶尔用一、二次。&#xD;
&amp;ldquo;对任何事物不究就里&amp;rdquo;是任何行业的工程师所不应该具备的素质。开发Windows应用程序，看看 Windows程序的设计、加载、执行原理，分析一下PE文件格式，试试用SDK开发从头开发一个Windows应用程序；用VC＋＋、&#xD;
Delphi、 Java、.Net开发应用程序，花时间去研究一下MFC、VCL、J2EE、.Net它们框架设计或者源码；除了会用J2EE、 JBoss、Spring、Hibernate等等优秀的开源产品或者框架，抽空看看大师们是如何抽象、分析、设计和实现那些类似问题的通用解决方案的。 试着这样做做，你以后的工作将会少遇到一些让你不明就里、一头雾水的问题，因为，很多东西你&amp;ldquo;知其然且知其所以然&amp;rdquo;！&lt;/p&gt;&#xD;
&lt;p&gt;7、在一种语言上编程，但别为其束缚了思想。&#xD;
&amp;ldquo;代码大全&amp;rdquo;中说：&amp;ldquo;深入一门语言编程，不要浮于表面&amp;rdquo;。深入一门语言开发还远远不足，任何编程语言的存在都有其自身的理由， 所以也没有哪门语言是&amp;ldquo;包治百病&amp;rdquo;的&amp;ldquo;灵丹妙药&amp;rdquo;。编程语言对开发人员解决具体问题的思路和方式的影响与束缚的例子俯拾皆是。&#xD;
我 的经验是：用面对对象工具开发某些关键模块时，为什么不可以借鉴C、C51、汇编的模块化封装方式？用传统的桌面开发工具（目前主要有VC++、 Delphi） 进行系统体统结构设计时，为什么不可以参考来自Java社区的IoC、AOP设计思想，甚至借鉴像Spring、Hibernate、JBoss等等优秀 的开源框架？在进行类似于实时通信、数据采集等功能的设计、实现时，为什么不可以引用来自实时系统、嵌入式系统的优秀的体系框架与模式？为什么一切都必须 以个人、团队在当然开发语言上的传统或者经验来解决问题？？？&amp;ldquo;他山之石、可以攻玉&amp;rdquo;。&lt;/p&gt;&#xD;
&lt;p&gt;8、养成总结与反思的习惯，并有意识地提炼日常工作成果，形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。&#xD;
众 所周知，对软件开发人员而言，有、无经验的一个显著区别是：无经验 者完成任何任务时都从头开始，而有经验者往往通过重组自己的可复用模块、类库来解决问题（其实这个结论不应该被局限在软件开发领域、可以延伸到很多方 面）。这并不是说，所有可复用的东西都必须自己实现，别人成熟的通过测试的成果也可以收集、整理、集成到自己的知识库中。但是，最好还是自己实现，这样没 有知识产权、版权等问题，关键是自己实现后能真正掌握这个知识点，拥有这个技能。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;9、理论与实践并重，内外双修。&#xD;
工程师 的内涵是：以工 程师的眼光观察、分析事物和世界。一个合格的软件工程师，是真正理解了软件产品的本质及软件产品研发的思想精髓的人（个人观点、欢迎探讨）。掌握软件开发 语言、应用语言工具解决工作中的具体问题、完成目标任务是软件工程师的主要工作，但从软件工程师这个角度来看，这只是外在的东西，并非重要的、本质的工 作。学习、掌握软件产品开发理论知识、软件开发方法论，并在实践中理解、应用软件产品的分析、设计、实现思想来解决具体的软件产品研发问题，才是真正的软 件工程师的工作。站在成熟理论与可靠方法论的高度思考、分析、解决问题，并在具体实践中验证和修正这些思想与方式，最终形成自己的理论体系和实用方法论。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;10、心态有多开放，视野就有多开阔。&#xD;
不 要抱着自己的技术和成果，等到它们都已经过时变成垃圾了，才拿出来丢人现眼。请及时发布自己的研究成果：开发的 产品、有创意的设计或代码，公布出来让大家交流或者使用，你的成果才有进化和升华的机会。想想自己2000年间开发的那些Windows系统工具，5、6 年之后的今天，还是那个样子，今天流行的好多Windows系统工具都比自己的晚，但进化得很好，且有那么多用户在使用。并且，不要保守自己的技术和思 想，尽可能地与人交流与分享，或者传授给开发团队的成员。&amp;ldquo;与人交换苹果之后，每个人还是只有一个苹果；但交换思想之后，每个人都拥有两种思想&amp;rdquo;，道理大 家都懂，但有多少人真正能做到呢？&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;11、尽量参加开源项目的开发、或者与朋友共同研制一些自己的产品，千万不要因为没有钱赚而不做。&#xD;
网 络早已不再只是&amp;ldquo;虚拟世界&amp;rdquo;，网上有很多的开源项目、合作开发项目、外包项目，这都是涉猎工作以外的知识的绝好机会，并且能够结识更广的人缘。不 要因为工 作是做ERP，就不去学习和了解嵌入式、实时、通信、网络等方面的技术，反过来也是一样。如果当别人拿着合同找你合作，你却这也不会，那也不熟时，你将后 悔莫及。&lt;/p&gt;&#xD;
&lt;p&gt;12、书到用时方恨少，不要将自己的知识面仅仅局限于技术方面。&#xD;
诺贝尔经济学奖得主西蒙教授的研究结果表明：&amp;ldquo;对于一个有一定基础的人来说，他只要真正肯下功夫，在6个月内就可以掌握任何一门学问。&amp;rdquo;教育心理学界为感谢西蒙教授的研究成果，故命名为西蒙学习法。&#xD;
可见，掌握一门陌生的学问远远没有想象的那么高难、深奥。多方吸取、广泛涉猎。极力夯实自己的影响圈、尽量扩大自己的关注圈。财务、经济、税务、管理等等知识，有空花时间看看，韬光养晦、未雨绸缪。&lt;/p&gt;&#xD;
&lt;p&gt;13、本文的总结与反思：&#xD;
A：不要去做技术上的高手，除非你的目标如此。虽然本文是关于提高软件开发知识的建议，做技术的高手是我一向都不赞同的。你可以提高自己的专业知识，但能胜任工作即止。&#xD;
B：提高软件知识和技术只是问题的表面，本质是要提高自己认识问题、分析问题、解决问题的思想高度。软件专业知识的很多方法和原理，可以很容易地延伸、应用到生活的其它方面。&#xD;
C：在能胜任工作的基础上，立即去涉猎其它领域的专业知识，丰富自己的知识体系、提高自己的综合素质，尤其是那些目标不在技术方面的朋友。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1710475.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/04/12/1710475.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/04/09/1708125.html</id><title type="text">[转]flex4的spark组件的皮肤制作方法。</title><summary type="text">http://bbs.airia.cn/FLEX/thread-8427-1-2.aspx原来看了很多flex3的书，提到皮肤时举例子基本上都是用图片或swf内含的矢量图，来分别替换控件的upskin、downskin、overskin&amp;hellip;&amp;hellip;等等。弄得我一直有一个错觉，好像皮肤就是这么回事，用图片替换。也就无法动态更改颜色大小等属性了。到了想定义spark控件皮肤的时候，...</summary><published>2010-04-09T03:16:00Z</published><updated>2010-04-09T03:16:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/04/09/1708125.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/04/09/1708125.html"/><content type="html">&lt;p&gt;&lt;span style="word-spacing: 0px; font: medium 'Times New Roman'; text-transform: none; color: #000000; text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px;" &gt;&lt;span style="font-size: 14px; line-height: 21px; font-family: Tahoma, Helvetica, Arial, sans-serif; border-collapse: collapse;" &gt;&lt;a href="http://bbs.airia.cn/FLEX/thread-8427-1-2.aspx"&gt;http://bbs.airia.cn/FLEX/thread-8427-1-2.aspx&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span style="word-spacing: 0px; font: medium 'Times New Roman'; text-transform: none; color: #000000; text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px;" &gt;&lt;span style="font-size: 14px; line-height: 21px; font-family: Tahoma, Helvetica, Arial, sans-serif; border-collapse: collapse;" &gt;原来看了很多flex3的书，提到皮肤时举例子基本上都是用图片或swf内含的矢量图，来分别替换控件的upskin、downskin、overskin&amp;hellip;&amp;hellip;等等。弄得我一直有一个错觉，好像皮肤就是这么回事，用图片替换。也就无法动态更改颜色大小等属性了。&lt;br /&gt;&lt;br /&gt;到了想定义spark控件皮肤的时候，才猛然发现，一个skin样式也没有了，这该怎么替换图片啊？唯独有一个skinclass的属性。&lt;br /&gt;&lt;br /&gt;经过摸索，原来是这么一回事啊：据官方文档的描述是，spark组件的出现大部分是为了围绕全面兼容&amp;ldquo;flash catalyst&amp;rdquo;的使用。spark组件就是跟mx平行的一套，功能既然都一样，那为什么要再写一套呢？这正是为了让spark组件能直接使用FC导出的皮肤文件！刚开始看网上的评论，一直说flex4的皮肤机制改进了，多好多好。然后给了个例子，发现完全是代码的。感觉靠想象力根本就写不出来嘛，哪有改进？具体的关于spark的skin是如何使用的，请看&lt;a target="_blank" href="http://www.k-zone.cn/zblog/post/flash-builder-gumbo-customer-sparkskin.html" style="color: #0066cc; text-decoration: none;"&gt;Flex SDK 4(Gumbo)更方便的自定义样式、自定义SparkSkin&lt;/a&gt;，别人说过的我就不多说了，里面很明白的说了，spark组件的skinclass是怎么用的。后来又看了一个非常棒的FC视频教程&lt;a target="_blank" href="http://www.gotoandlearn.com/play?id=110" style="color: #0066cc; text-decoration: none;"&gt;&lt;span style="font-size: x-small;"&gt;Flash Catalyst and Flex 4: Part 1&lt;/span&gt;&lt;/a&gt;，顿时明白了，sparkskin原来根本不是用手写的，是直接画出来生成的。。。。。。&lt;br /&gt;&lt;br /&gt;看完那个视频教程，你就会明白spark皮肤制作原来是这么的简单！我之后就开始深入AI的矢量图绘画了，把原来图片格式的皮肤都画了一遍，导入FC，再导出就都变代码化皮肤了。因为是代码化的，导出文件变得非常的小，而且由于代码化的好处，属性完全就在你的掌控之中了，可以运行时任意修改皮肤颜色等外观，完全可以做自定义皮肤了。&lt;img emoticon="[em:42]" width="24" src="http://www.cnblogs.com/max-assets/icon-emoticon/42.gif" height="24" style="cursor: pointer; border-width: 0px;" /&gt;（另外小小提示一下：AI里有些效果，比如说径向的渐变在FC里不能被很好的导入，会发生外观差别，我的技巧是，把矢量栅格化了，变成位图，导入FC后，一样可以使用。即使无法完全代码化，也依然推荐这么制作皮肤，因为位图的话是可以半透明的，你还是可以动态更改皮肤的背景颜色，也可以动态设置位图的透明度，控制力 还是很大滴。导出的皮肤会混合代码图和位图，不用担心，这些FC都为你编写好啦）&lt;br /&gt;&lt;br /&gt;以上是学会了如何制作代码化的sparkskin，我后来更进了一步，琢磨怎么把代码化的皮肤用在MX组件上（嘿嘿，很邪恶吧？这样以后只要想要的外观都可以直接画了，导入FC转换就行啦，没办法，FC制作皮肤太简单了！）说这个之前，还是请大家回到前面提到的那篇文章吧，弄清楚mxskin和sparkskin的关系了，下面的问题就明朗了。&lt;br /&gt;&lt;br /&gt;先来看下sparkskin是在css里是怎么定义的&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p style="border-right: #cadcea 1px solid; border-top: #cadcea 1px solid; font-weight: normal; font-size: 0.85em; margin: 10px 0px; border-left: #cadcea 3px solid; border-bottom: #cadcea 1px solid; font-style: normal; font-family: inherit; background-color: #ffffff; background-origin: initial; background-clip: initial; padding: 0px;" &gt;&lt;p style="padding-right: 10px; background-position: 10px 50%; padding-left: 25px; font-weight: normal; font-size: 1em; background-image: url(http://bbs.airia.cn/max-templates/default/img/icon/code.gif); padding-bottom: 0px; margin: 0px; line-height: 2; padding-top: 0px; border-bottom: #cccccc 1px dashed; font-style: normal; font-family: inherit; height: 2em; background-origin: initial; background-clip: initial;"&gt;代码&lt;span &gt;&amp;nbsp;&lt;/span&gt;&lt;a href="javascript:;" onclick="ubbCopy(this)" style="color: #0066cc; text-decoration: none;" &gt;复制&lt;/a&gt;&lt;span &gt;&amp;nbsp;&lt;/span&gt;-&lt;span &gt;&amp;nbsp;&lt;/span&gt;&lt;a href="javascript:;" onclick="ubbRun(this)" style="color: #0066cc; text-decoration: none;" &gt;运行&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;pre&gt;&lt;code style="padding-right: 10px; display: block; padding-left: 10px; padding-bottom: 5px; padding-top: 5px; font-family: Consolas, 'Courier New', monospace;"&gt;s|Button {       skinClass: ClassReference("com.rianote.flex.skin.KButton"); } &lt;/code&gt;&lt;/pre&gt;&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;看着跟mx的定义是不是很像？那就对了。我们只需要这么改：&lt;/p&gt;&#xD;
&lt;p style="border-right: #cadcea 1px solid; border-top: #cadcea 1px solid; font-weight: normal; font-size: 0.85em; margin: 10px 0px; border-left: #cadcea 3px solid; border-bottom: #cadcea 1px solid; font-style: normal; font-family: inherit; background-color: #ffffff; background-origin: initial; background-clip: initial; padding: 0px;" &gt;&lt;p style="padding-right: 10px; background-position: 10px 50%; padding-left: 25px; font-weight: normal; font-size: 1em; background-image: url(http://bbs.airia.cn/max-templates/default/img/icon/code.gif); padding-bottom: 0px; margin: 0px; line-height: 2; padding-top: 0px; border-bottom: #cccccc 1px dashed; font-style: normal; font-family: inherit; height: 2em; background-origin: initial; background-clip: initial;"&gt;代码&lt;span &gt;&amp;nbsp;&lt;/span&gt;&lt;a href="javascript:;" onclick="ubbCopy(this)" style="color: #0066cc; text-decoration: none;" &gt;复制&lt;/a&gt;&lt;span &gt;&amp;nbsp;&lt;/span&gt;-&lt;span &gt;&amp;nbsp;&lt;/span&gt;&lt;a href="javascript:;" onclick="ubbRun(this)" style="color: #0066cc; text-decoration: none;" &gt;运行&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;pre&gt;&lt;code style="padding-right: 10px; display: block; padding-left: 10px; padding-bottom: 5px; padding-top: 5px; font-family: Consolas, 'Courier New', monospace;"&gt;mx|Button {       upSkin: ClassReference("com.rianote.flex.skin.KButton"); } &lt;/code&gt;&lt;/pre&gt;&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;这里只定义了upskin,跟用图片没什么区别的，然后你再分别定义downSkin、overskin&amp;hellip;&amp;hellip;就可以了。这只解决了一半，关键是要修改那个com.rianote.flex.skin.KButton皮肤类文件，因为它是为spark生成的，我们修改一下，才能让mx也能用。打开文件代码如下： &lt;/p&gt;&#xD;
&lt;p style="border-right: #cadcea 1px solid; border-top: #cadcea 1px solid; font-weight: normal; font-size: 0.85em; margin: 10px 0px; border-left: #cadcea 3px solid; border-bottom: #cadcea 1px solid; font-style: normal; font-family: inherit; background-color: #ffffff; background-origin: initial; background-clip: initial; padding: 0px;" &gt;&lt;p style="padding-right: 10px; background-position: 10px 50%; padding-left: 25px; font-weight: normal; font-size: 1em; background-image: url(http://bbs.airia.cn/max-templates/default/img/icon/code.gif); padding-bottom: 0px; margin: 0px; line-height: 2; padding-top: 0px; border-bottom: #cccccc 1px dashed; font-style: normal; font-family: inherit; height: 2em; background-origin: initial; background-clip: initial;"&gt;代码&lt;span &gt;&amp;nbsp;&lt;/span&gt;&lt;a href="javascript:;" onclick="ubbCopy(this)" style="color: #0066cc; text-decoration: none;" &gt;复制&lt;/a&gt;&lt;span &gt;&amp;nbsp;&lt;/span&gt;-&lt;span &gt;&amp;nbsp;&lt;/span&gt;&lt;a href="javascript:;" onclick="ubbRun(this)" style="color: #0066cc; text-decoration: none;" &gt;运行&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;pre&gt;&lt;code style="padding-right: 10px; display: block; padding-left: 10px; padding-bottom: 5px; padding-top: 5px; font-family: Consolas, 'Courier New', monospace;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt; &amp;lt;s:Skin xmlns:s="library://ns.adobe.com/flex/spark" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:ai="http://ns.adobe.com/ai/2009"&amp;gt;  &amp;lt;fx:Metadata&amp;gt;[HostComponent("spark.components.Button")]&amp;lt;/fx:Metadata&amp;gt;  &amp;lt;s:states&amp;gt;   &amp;lt;s:State name="up"/&amp;gt;   &amp;lt;s:State name="over"/&amp;gt;   &amp;lt;s:State name="down"/&amp;gt;   &amp;lt;s:State name="disabled"/&amp;gt;  &amp;lt;/s:states&amp;gt;  &amp;lt;s:Path alpha="0.95" data="M 99.502 35.5 L 0.5 35.5 L 0.5 9.68 C 0.5 4.61 5.566 0.5 11.815 0.5 L 88.187 0.5 C 94.435 0.5 99.502 4.61 99.502 9.68 L 99.502 35.5 Z" ai:objID="4c09c580" winding="nonZero" x="0" y="0"&amp;gt;   &amp;lt;s:fill&amp;gt;    &amp;lt;s:LinearGradient scaleX="99.0015" x="0.5" y="18"&amp;gt;     &amp;lt;s:GradientEntry color="0x4E4E4E" ratio="0.5"/&amp;gt;     &amp;lt;s:GradientEntry color="0x545454" ratio="0.745455"/&amp;gt;     &amp;lt;s:GradientEntry color="0x5B5B5B" ratio="1"/&amp;gt;    &amp;lt;/s:LinearGradient&amp;gt;   &amp;lt;/s:fill&amp;gt;   &amp;lt;s:stroke&amp;gt;    &amp;lt;s:SolidColorStroke caps="none" color="0x6A6A6A" joints="miter" miterLimit="4" scaleMode="normal" weight="1"/&amp;gt;   &amp;lt;/s:stroke&amp;gt;  &amp;lt;/s:Path&amp;gt;  &amp;lt;s:Path alpha="0.95" data="M 0 23.187 L 0 4.229 C 0 4.229 22.572 -4.313 50 2.771 C 77.427 9.854 100 1.312 100 1.312 L 100 23.187 L 0 23.187 Z" ai:objID="4c177400" winding="nonZero" x="0" y="13"&amp;gt;   &amp;lt;s:fill&amp;gt;    &amp;lt;s:LinearGradient rotation="270" scaleX="23.2266" x="50.0005" y="23.2266"&amp;gt;     &amp;lt;s:GradientEntry ratio="0"/&amp;gt;     &amp;lt;s:GradientEntry color="0x333333" ratio="1"/&amp;gt;    &amp;lt;/s:LinearGradient&amp;gt;   &amp;lt;/s:fill&amp;gt;  &amp;lt;/s:Path&amp;gt; &amp;lt;/s:Skin&amp;gt; &lt;/code&gt;&lt;/pre&gt;&#xD;
&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;观察了一下，FC现在导出的皮肤根标签已经就直接是skin了，而不是sparkSkin，那么当然就可以直接给mx用了啊。&lt;br /&gt;只要删去这几个部分：1、&amp;lt;fx:Metadata&amp;gt;&amp;hellip;&amp;hellip;&amp;lt;/fx:Metadata&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2、&amp;lt;s:states&amp;gt; &amp;hellip;&amp;hellip;&amp;lt;s:states&amp;gt;这样保留下来的就只有绘图函数代码了。&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;3、如果你也是用AI画的皮肤，你就也会有xmlns:ai=&lt;a target="_blank" href="http://ns.adobe.com/ai/2009" style="color: #0066cc; text-decoration: none;"&gt;http://ns.adobe.com/ai/2009&lt;/a&gt;这个命名空间，删掉它，同时把代码部分里出现ai属性的地方都删除，如：ai:objID="4c177400"这种。&lt;br /&gt;&lt;br /&gt;OK！现在就能完美把FC导出的代码化皮肤加给mx用啦。你看我说的麻烦，你操作一下就会发现，这其实很简单的。&lt;br /&gt;&lt;br /&gt;最后再说一下，怎么在运行时动态设置皮肤的颜色等外观。运行时皮肤只能通过一种途径跟调用它的控件通信，就是getStyle（）方法。用这个方法获取当前控件的一个style属性值。例如&amp;lt;s:GradientEntry color="0x333333" ratio="1"/&amp;gt; 这句就可以改成&amp;lt;s:GradientEntry color="{getStyle('color')}" ratio="1"/&amp;gt; 然后运行时去设置那个Button的color属性就可以了。&lt;br /&gt;&lt;br /&gt;啊，打字打累了，就说这么多了吧，也不知道说明白了没，希望对看的人有帮助啊。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1708125.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/04/09/1708125.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/03/29/1699996.html</id><title type="text">[转]Flex SDK coding conventions and best practices</title><summary type="text">网址copy过来...命名规范:http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions</summary><published>2010-03-29T13:19:00Z</published><updated>2010-03-29T13:19:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/03/29/1699996.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/03/29/1699996.html"/><content type="html">&lt;p&gt;网址copy过来...&lt;/p&gt;&#xD;
&lt;p&gt;命名规范:&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions"&gt;http://opensource.adobe.com/wiki/display/flexsdk/Coding+Conventions&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1699996.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/03/29/1699996.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/03/17/1687755.html</id><title type="text">[转]cacheAsBitmap使用</title><summary type="text">该用cacheAsBitmap的时候：效率提升只适用于x,y的改变，然而，一旦牵涉形变（旋转，缩放）效率只会更低下。一个复杂的矢量化背景图片上存在大量动画；滚动文本区域；基于窗口的应用（你经常会拖拽整块区域）透明遮罩（必须强制使用，否则失效）不应该用cacheAsBitmap的时候：不要滥用，cacheAsBitamp十分消耗内存，一块250&amp;times;250像素的矩形进行cache之后可能占掉...</summary><published>2010-03-16T16:25:00Z</published><updated>2010-03-16T16:25:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/03/17/1687755.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/03/17/1687755.html"/><content type="html">&lt;p&gt;&lt;strong style="font-weight: bold;"&gt;该用cacheAsBitmap的时候：&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.5em; margin-left: 0px; padding: 0px;"&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;效率提升只适用于x,y的改变，然而，一旦牵涉形变（旋转，缩放）效率只会更低下。&lt;/li&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;一个复杂的矢量化背景图片上存在大量动画；&lt;/li&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;滚动文本区域；&lt;/li&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;基于窗口的应用（你经常会拖拽整块区域）&lt;/li&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;透明遮罩（必须强制使用，否则失效）&lt;/li&gt;&#xD;
&lt;/ul&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;strong style="font-weight: bold;"&gt;不应该用cacheAsBitmap的时候：&lt;/strong&gt;&amp;nbsp;&lt;/p&gt;&#xD;
&lt;ul style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.5em; margin-left: 0px; padding: 0px;"&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;不要滥用，cacheAsBitamp十分消耗内存，一块250&amp;times;250像素的矩形进行cache之后可能占掉250kb的内存！&lt;/li&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;目标元素缩放的时候不要使用。&lt;/li&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;目标元素本身最好是静态的，或者不要经常发生翻转、缩放这样的动画&lt;/li&gt;&#xD;
&lt;li style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.25em; margin-left: 30px; padding: 0px;"&gt;不要把矢量图和cache的位图一起混用。&lt;/li&gt;&#xD;
&lt;/ul&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1687755.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/03/17/1687755.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/03/15/1686290.html</id><title type="text">[转]Updated ‘Elastic Racetrack’ for Flash 9 and AVM2</title><summary type="text">In 2005 Ted Patrick posted a great article on the frame execution model inside the Flash Player that he dubbed the &amp;lsquo;elastic racetrack&amp;lsquo;. It&amp;rsquo;s served as a great reference for me over t...</summary><published>2010-03-15T07:43:00Z</published><updated>2010-03-15T07:43:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/03/15/1686290.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/03/15/1686290.html"/><content type="html">&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;In 2005 Ted Patrick posted a great article on the frame execution model inside the Flash Player that he dubbed the &amp;lsquo;&lt;a href="http://www.onflex.org/ted/2005/07/flash-player-mental-model-elastic.php" title="Flash Elastic Racetrack" style="color: #991100; font-weight: bold;"&gt;elastic racetrack&lt;/a&gt;&amp;lsquo;. It&amp;rsquo;s served as a great reference for me over the years to help understand how code execution and rendering were balanced within the processing of a frame. Since the introduction of Flash Player 9 and the new AVM2, I&amp;rsquo;ve noticed a few changes to the elastic racetrack model and thought I&amp;rsquo;d share them. This information is based on research into Flash player internals as well as observations I&amp;rsquo;ve made playing around with the event and rendering model, but the full model hasn&amp;rsquo;t been confirmed by Adobe engineers.&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;The basic premise of the original elastic racetrack is still the same. Given a specific frame rate to operate on, the Flash player will devote the first segment of the frame to execute code, and the second segment to render display objects. Either segment can grow its part of the racetrack to accommodate more processing and effectively extend the duration of the frame.&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em; text-align: center;"&gt;&lt;img src="http://www.craftymind.com/wp-content/uploads/2008/04/elasticracetrackexport.png" alt="Flash Player Elastic Racetrack" /&gt;&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;What changes from the previous model is how those segments look under a microscope and how they come together to form a &amp;lsquo;frame&amp;rsquo;.&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;AVM2 is controlled by what I&amp;rsquo;m going to call the Marshal. The Marshal is responsible for carving out time slices for the Flash Player to operate on. Its important to clarify up front that these time slices are not the same thing as the framerate compiled into a swf, but we&amp;rsquo;ll see below how the player ultimately synthesizes a framerate from these slices. Running a Flex compiled swf within Firefox under Mac OS X, the Marshal appears to be carving out 19-20 millisecond slices, but this can be different between platforms and browsers based on what I&amp;rsquo;ve observed as well as Adobe employees have&amp;nbsp;&lt;a href="http://www.jamesward.org/wordpress/2008/04/10/bursting-bubbles/" style="color: #991100; font-weight: bold;"&gt;hinted at&lt;/a&gt;. This can also change depending on how the swf was compiled, see some of the comments below. For the sake of the article lets assume we&amp;rsquo;re only talking about a 20 millisecond slice to make the math easy. This means the Marshal will attempt to generate and execute no more then 50 slices each second, and it may be less depending on the elasticity of code execution or rendering. Inside each slice, 5 possible steps are processed in the following order.&lt;/p&gt;&#xD;
&lt;ol style="margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 40px; font-size: 1.2em;"&gt;&#xD;
&lt;li&gt;Player events are dispatched - This includes events dispatched by the Timer, Mouse, ENTER_FRAMEs, URLLoader, etc&amp;hellip;&lt;/li&gt;&#xD;
&lt;li&gt;User code is executed - Any code listening to events dispatched by step 1 are executed at this stage.&lt;/li&gt;&#xD;
&lt;li&gt;RENDER event is dispatched - This special event is dispatched when the user calls stage.invalidate() during normal user code operation.&lt;/li&gt;&#xD;
&lt;li&gt;Final user code is executed - User code listening specifically for step 3 is executed at this point.&lt;/li&gt;&#xD;
&lt;li&gt;Player renders changes to the display list.&lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em; text-align: center;"&gt;&lt;img src="http://www.craftymind.com/wp-content/uploads/2008/04/marshalledsliceexport.png" alt="AVM2 Marshalled Slice" /&gt;&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;The Marshal executes this 20 millisecond slice over and over and decides on the fly which actions to run. The exact actions processed within a slice will ultimately derive the 2 main racetrack segments (code execution and rendering) that constitute a &amp;lsquo;frame&amp;rsquo;. User actions and Invalidation actions fill up the code segment track, while Render actions fill up the render segment track. Its important to note that actions will only occur at times predetermined by the Marshal, so a if you have a short running User action, the Marshal will still wait a few milliseconds before moving on to the Invalidate and Render actions.&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;The best way to illustrate which actions are run and how the elastic racetrack is created, is to look at how those slices are processed on a swf running at 5 fps, 25, fps, and 50 fps.&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;&lt;img height="350" width="1200" src="http://www.craftymind.com/wp-content/uploads/2008/04/framemarshalingexport.png" /&gt;&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; overflow-x: scroll; overflow-y: scroll; width: 650px; margin: auto;"&gt;&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;As you can see, the elastic racetrack performs different actions per frame and requires a different visual illustration depending on the framerate that the player is trying to synthesize. So for a swf running at 5 fps, each frame processed 10 User actions, 1 Invalidation action, and 1 Render action. At 25 fps, each frame processed 2 User actions, 1 Invalidation action, and 1 Render action. At 50 fps, each frame processed 1 User action, 1 Invalidation action, and 1 Render action. Whats important to note in the above chart is that some events are only available in certain slices. For instance, the Event.ENTER_FRAME event will only ever be dispatched in a slice that occurs at the start of a frame.&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;So what does this all mean? Theres a couple quick ideas to take away from this.&lt;/p&gt;&#xD;
&lt;ol style="margin-top: 0px; margin-right: 0px; margin-bottom: 20px; margin-left: 40px; font-size: 1.2em;"&gt;&#xD;
&lt;li&gt;Long running code execution or render segments can extend a given slice beyond 20 milliseconds. Elasticity will be applied to that particular slice and the duration of the frame may or may not be extended as a result. The Marshal may drop the number of slices that constitute a frame in order to keep the active framerate close to the compiled framerate.&lt;/li&gt;&#xD;
&lt;li&gt;A swfs&amp;nbsp;&lt;em&gt;real&lt;/em&gt;&amp;nbsp;framerate won&amp;rsquo;t exceed the Marshals rate defined for the player instance. You can set your compiled framerate at 120fps, but Flash will still only process 50 slices max that generate 50 render calls (more or less depending on the system config).&lt;/li&gt;&#xD;
&lt;li&gt;Code can be executed more often then the compiled framerate. A swf compiled at 1 fps can execute a Timer or Mouse event in every slice, even though it will only render in the last slice. Additionally, if you choose, you can render to the screen sooner then the compiled framerate by calling updateAfterEvent() , but only within a Mouse, Timer, or Keyboard event handler. In this instance though, the Marshal will consider that the end of the frame and start a new frame on the next slice. Lastly, Flash will force an automatic render when mousing over any Sprite that has had its visual properties (x,y,width,height,etc..) changed, naturally this still occurs at the end of the slice and any prerender logic will still run.&lt;/li&gt;&#xD;
&lt;li&gt;Compiling a framerate that isn&amp;rsquo;t a multiple of the total number of slices per second for your platform will cause irregular rendering as it tries to divide up the slices. If you were to compile in a framerate of 20 on a platform executing 50 slices per second, then the player has to render 2 frames every 5 slices and would follow a 3-2-3-2-3-2 slice-to-render rate.&lt;/li&gt;&#xD;
&lt;/ol&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;These 4 facts are moving targets though, since for this article we&amp;rsquo;re working on a 20 millisecond slice that&amp;rsquo;s processed 50 times per second. In reality you&amp;rsquo;ll see time slices as low as 5 milliseconds or as high at 100 milliseconds and some of the math will change as a result.&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;If you&amp;rsquo;d like to test this model for yourself, the easiest route is to create a swf running at 1 fps and another at 100 fps both with a Timer object set on a 1 millisecond interval. Inside the Timer event handler change the x property of a display object and hook a bunch of getTimer() traces up to different player events like Mouse, EnterFrame, and Render and watch the carnage unfold in your console. The rest of the information you can&amp;rsquo;t derive from the results comes from alot of context about the player I&amp;rsquo;ve learned over the past 2 years and so isn&amp;rsquo;t as easily visible. If anyone has any information to help add to or correct the above model, please submit it in the comments.&lt;/p&gt;&#xD;
&lt;p style="font-size: 1.3em; margin-left: 10px; margin-bottom: 1em;"&gt;Thanks to several readers who have clarified some of the differences between Flex and Flash as well as how the Flash API is able to change the default behaviors described above.&lt;/p&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1686290.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/03/15/1686290.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/02/26/1674192.html</id><title type="text">[转]Flex和AIR中的垃圾回收实践之对象缓存[译文]</title><summary type="text">转自:http://www.riameeting.com/node/587原文在这里：Garbage Collection with Flex and Adobe Air 我终于有时间来整理在flexcamp上演讲的东西并写篇博客了。就在flexcamp前一个月，我几乎天天和FlexProfiler争吵而且关系很紧张（笔者注：结论不一致）。因此我觉得在flexcamp中讲讲性能监测和垃圾回收（GC...</summary><published>2010-02-26T05:05:00Z</published><updated>2010-02-26T05:05:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/02/26/1674192.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/02/26/1674192.html"/><content type="html">&lt;p&gt;转自:http://www.riameeting.com/node/587&lt;/p&gt;&#xD;
&lt;p&gt;原文在这里：&lt;a href="http://spreadingfunkyness.com/garbage-collection-with-flex-and-adobe-air/" target="_blank"&gt;Garbage Collection with Flex and Adobe Air &lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;我终于有时间来整理在flexcamp上演讲的东西并写篇博客了。就在flexcamp前一个月，我几乎天天和FlexProfiler争吵而且关系很紧张（笔者注：结论不一致）。因此我觉得在flexcamp中讲讲性能监测和垃圾回收（GC）是非常合适的话题。没错，想要脱离GC去获得性能提升简直是不可能的。如果你想改善你的应用的内存管理你必须知道Flashplayer（和adobe AIR）如何管理内存分配和释放。&lt;/p&gt;&#xD;
&lt;p&gt;有许多博客、文章、演讲、等等都介绍过GC和profiling，我在文章底部将他们列举了出来。对于每天使用Flex并且需要来优化内存消耗的初学者和中等经验的开发者来说，我这篇文章是有帮助意义的。&lt;/p&gt;&#xD;
&lt;p&gt;虚拟机(VM)&lt;/p&gt;&#xD;
&lt;p&gt;flashplayer是基于一个虚拟机（精确的来说是2两个，一个是为actionscript2的一个是为actionscript3的），当你需要创建新的对象时虚拟机动态分配内存，例如下面的代码来创建一个新的对象：&lt;/p&gt;&#xD;
&lt;p&gt;var o:Object = new Object();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;在启动时VM事先占用（reserve）了一些内存，当上面的代码被执行时VM决定那个对象放在应用内存的什么位置以及它需要占用多少空间。当你创建对象时，VM可能使用启动时占用的所有内存，如果需要，再向操作系统请求更多的内存。除非你有一个程序仅仅是毫无疑义的创建新对象，正常的应用在执行时必然会有一个对象变为无用的时候，例如，为了正确的执行程序，它不需要存在了。你将会看到，理解一个对象何时不再被需要是不容易的事情。就现在，让我们加深我们能够检测到它。在Flash VM架构，你不能明确的说&amp;ldquo;删除它&amp;rdquo;，内存使用是被VM本身所管理的，VM本身负责检查哪些对象是无用的并擅长他们，这样的机制就叫做垃圾回收。&lt;/p&gt;&#xD;
&lt;p&gt;垃圾回收&lt;/p&gt;&#xD;
&lt;p&gt;那么，作为一个程序员我们能做什么？好的，你可以让垃圾回收变得容易，让我们来看看下图能为我们揭示什么内容。&lt;br /&gt;&lt;img src="http://spreadingfunkyness.com/wp-content/uploads/2009/01/memblocks.gif" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在启动阶段应用占用了一些要使用的内存，比如说4个块。当你创建了一个对象，VM将第一个空位分配给它。我们说，过一会当o1不再需要是你将它设为null。你创建一个新的对象o2，你希望o2代替o1。有时它发生，有时它不会发生，这取决于垃圾回收机制，这样一种非常复杂的过程，我们不在这里描述。这时我们已经得到一个教训：&amp;ldquo;设置一个对象为null不一定能够释放它占用的内存&amp;rdquo;。这取决于flash中已经实现的垃圾回收的方式，GC由重分配触发而不是由删除触发，这意味着GC周期在你声明new Object()的时候运行而不是你设置它为null时运行。&lt;/p&gt;&#xD;
&lt;p&gt;内存消耗&lt;/p&gt;&#xD;
&lt;p&gt;如果你不得不使用AS3和Flex，你可能知道你可以动态的添加UI元素到图形界面中，通过一个简单的方法叫做addChild()，相反的方法是removeChild()，它用来移除一个显示元素从UI中。更精确的来说，元素是从视图中删除，但是这不意味着它已经被垃圾回收了。让我来介绍一个简单的场景给你展示很容易相信removeChild()的事实。&lt;/p&gt;&#xD;
&lt;p&gt;许多Flex应用从服务端加载数据并根据返回的值动态展示它，通常情况视图代码被隔离到一个组件中，经常被称为renderer，它负责展示来自服务器的数据。我没设计一个非常简单的renderer，它由两个文本字段，嵌入一个VBox中，数据显示是field1和field2，被提供的对象的属性作为值来源：&lt;/p&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #009900;"&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;lt;mx:VBox&lt;/span&gt; &lt;span style="color: #000066;"&gt;xmlns:mx&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"http://www.adobe.com/2006/mxml"&lt;/span&gt; &lt;/span&gt;&lt;span style="color: #009900;"&gt;    &lt;span style="color: #000066;"&gt;borderStyle&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"solid"&lt;/span&gt; &lt;span style="color: #000066;"&gt;width&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"200"&lt;/span&gt; &lt;/span&gt;&lt;span style="color: #009900;"&gt;    &lt;span style="font-weight: bold; color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;    &lt;span style="color: #009900;"&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;lt;mx:Script&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;        &lt;span style="color: #339933;"&gt;&amp;lt;![CDATA[&lt;/span&gt;&lt;span style="color: #339933;"&gt;    [Bindable] private var _field1:String;&lt;/span&gt;&lt;span style="color: #339933;"&gt;    [Bindable] private var _field2:String;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #339933;"&gt;    override public function set data(value:Object):void {&lt;/span&gt;&lt;span style="color: #339933;"&gt;_field1 = value.field1;&lt;/span&gt;&lt;span style="color: #339933;"&gt;_field2 = value.field2;&lt;/span&gt;&lt;span style="color: #339933;"&gt;    }&lt;/span&gt;&lt;span style="color: #339933;"&gt;]]&amp;gt;&lt;/span&gt;&lt;span style="color: #009900;"&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;lt;/mx:Script&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #009900;"&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;lt;mx:Text&lt;/span&gt; &lt;span style="color: #000066;"&gt;text&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"{_field1}"&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #009900;"&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;lt;mx:Text&lt;/span&gt; &lt;span style="color: #000066;"&gt;text&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"{_field2}"&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #009900;"&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;lt;/mx:VBox&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;让我们通过一个简单的函数来模拟数据载入，它返回对象的一个数组：&lt;/p&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;private&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;function&lt;/span&gt; getData&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;:&lt;span style="color: #0066cc;"&gt;Array&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="font-weight: bold; color: #000000;"&gt;var&lt;/span&gt; a:&lt;span style="color: #0066cc;"&gt;Array&lt;/span&gt; = &lt;span style="font-weight: bold; color: #000000;"&gt;new&lt;/span&gt; &lt;span style="color: #0066cc;"&gt;Array&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;&amp;nbsp;  &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #b1b100;"&gt;for&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;var&lt;/span&gt; i:uint = &lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt;; i&lt;span style="color: #66cc66;"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #cc66cc;"&gt;200&lt;/span&gt;; i++&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;　　{&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;　　　　var&lt;/span&gt; o:&lt;span style="color: #0066cc;"&gt;Object&lt;/span&gt; = &lt;span style="font-weight: bold; color: #000000;"&gt;new&lt;/span&gt; &lt;span style="color: #0066cc;"&gt;Object&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;o.&lt;span style="color: #006600;"&gt;field1&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;"field "&lt;/span&gt;+&lt;span style="color: #0066cc;"&gt;Math&lt;/span&gt;.&lt;span style="color: #0066cc;"&gt;random&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;.&lt;span style="color: #0066cc;"&gt;toString&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;o.&lt;span style="color: #006600;"&gt;field2&lt;/span&gt; = &lt;span style="color: #ff0000;"&gt;"field "&lt;/span&gt;+&lt;span style="color: #0066cc;"&gt;Math&lt;/span&gt;.&lt;span style="color: #0066cc;"&gt;random&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;.&lt;span style="color: #0066cc;"&gt;toString&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;a.&lt;span style="color: #0066cc;"&gt;push&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;o&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;  &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; a;&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;为了渲染数据，我们使用一个简单的函数，来创建一个renderer，设置它的data属性，并添加到VBox中：&lt;/p&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;private&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;function&lt;/span&gt; loadData&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;:&lt;span style="color: #0066cc;"&gt;void&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;  &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;vbox.&lt;span style="color: #006600;"&gt;removeAllChildren&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;   &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="font-weight: bold; color: #000000;"&gt;var&lt;/span&gt; &lt;span style="color: #0066cc;"&gt;array&lt;/span&gt;:&lt;span style="color: #0066cc;"&gt;Array&lt;/span&gt; = getData&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;&amp;nbsp;   &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #b1b100;"&gt;for&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;var&lt;/span&gt; i:&lt;span style="color: #0066cc;"&gt;int&lt;/span&gt; = &lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt;; i &lt;span style="color: #66cc66;"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #0066cc;"&gt;array&lt;/span&gt;.&lt;span style="color: #0066cc;"&gt;length&lt;/span&gt;; i++&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;　　{&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;　　var&lt;/span&gt; rend:MyRenderer = &lt;span style="font-weight: bold; color: #000000;"&gt;new&lt;/span&gt; MyRenderer&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;rend.&lt;span style="color: #0066cc;"&gt;data&lt;/span&gt; = &lt;span style="color: #0066cc;"&gt;array&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;[&lt;/span&gt;i&lt;span style="color: #66cc66;"&gt;]&lt;/span&gt;;box.&lt;span style="color: #006600;"&gt;addChild&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;rend&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;     &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;i++;   &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;　　}&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;你看到那个危险的声明了吗？还没有？让我来显示给你，为了模拟一个重复的操作，我添加了一个timer，它会每N秒都调用加载数据的函数：&lt;/p&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;private&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;function&lt;/span&gt; init&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;:&lt;span style="color: #0066cc;"&gt;void&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;   &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="font-weight: bold; color: #000000;"&gt;　　var&lt;/span&gt; t:Timer = &lt;span style="font-weight: bold; color: #000000;"&gt;new&lt;/span&gt; Timer&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #cc66cc;"&gt;2000&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;  &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;t.&lt;span style="color: #006600;"&gt;addEventListener&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;TimerEvent.&lt;span style="color: #006600;"&gt;TIMER&lt;/span&gt;, tick&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;   &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;t.&lt;span style="color: #0066cc;"&gt;start&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;现在，试着运行一下profiler（笔者注：flexbuilder3中的工具），你看到像下图一样一直增长的图形了吗？&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://spreadingfunkyness.com/wp-content/uploads/2009/01/growing.gif" /&gt;&lt;br /&gt;恭喜，我们已经发现了一个内存泄漏！内存泄漏发生在重复的动作并且内存消耗持续增长而不是保持恒定。你发现了那个危险的声明了吗？它就是当你创建renderer是发生的。为什么？因为你认为removeAllChildren()从内存中移除了那些renderers。错误！正像上面所说，这个方法仅仅从显示树（显示列表）中移除了renderers，事实上，正如你从profiler中看到的，renderers还在那儿，继续消耗着内存。&lt;/p&gt;&#xD;
&lt;p&gt;技术上讲这不是一个内存泄漏，因为这没有任何东西阻止垃圾回收器去清除来自renderers的内存。事实上这种情形下，内存泄漏发生在，当有些对象被认为使用了renderer（例如一个listener），即使当你从显示树中移除了它。在这个例子中renderers是&amp;ldquo;自由的&amp;rdquo;，可能被垃圾回收，但是，他们不是这样的，因此，结果仍然与内存泄漏是相同的，不断增长的内存消耗：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://spreadingfunkyness.com/wp-content/uploads/2009/01/instancescount.gif" /&gt;&lt;br /&gt;有许多技术来解决这种情况，我们来展示两个：缓存renderers和动态缓存。&lt;/p&gt;&#xD;
&lt;p&gt;缓存&lt;/p&gt;&#xD;
&lt;p&gt;让我们假设，你实现知道需要多少renderers，一个方法来解决内存泄漏就是在启动是来创建一个renderers的缓存：&lt;/p&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;&lt;p&gt;&lt;/p&gt;&lt;pre &gt;private var cache:Array = new Array(); &#xD;
private function initRenderers():void {   &#xD;
 for (var i:int = 0; i &amp;lt; 200; i++)&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;{renderers.push(new MyRenderer());    }&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;我们于是可以这样修改我们的loadData方法：&lt;/p&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;&lt;pre &gt;private function loadData():void {  &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;container.removeAllChildren();   &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;var array:Array = getData();   &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;for (var i:int = 0; i &amp;lt; array.length; i++)&lt;/pre&gt;&#xD;
&lt;pre &gt;{var rend:MyRenderer = cache[i];rend.data = array[i];  container.addChild(rend);i++;    }&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;}&#xD;
&lt;/pre&gt;&#xD;
&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;正如你所见，我们不再创建新的renderers，而是在缓存中查找一个。&lt;/p&gt;&#xD;
&lt;p&gt;很多情况下，你事先不知道多少数据从服务器返回，而且不知道你需要多少renderers，这时你需要一个动态缓存。&lt;/p&gt;&#xD;
&lt;p&gt;动态缓存&lt;/p&gt;&#xD;
&lt;p&gt;动态缓存是基于一个弹性的机制，你有一个地方可以来查找一个renderer：如果缓存中有一个，那就返回它，否则一个新的被临时创建，最好来看看下面的代码：&lt;/p&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;public&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;class&lt;/span&gt; MyRendererCache &lt;span style="color: #0066cc;"&gt;extends&lt;/span&gt; &lt;span style="color: #0066cc;"&gt;Object&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;&amp;nbsp;  &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;private&lt;/span&gt; &lt;span style="color: #0066cc;"&gt;static&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;var&lt;/span&gt; cache : ArrayCollection = &lt;span style="font-weight: bold; color: #000000;"&gt;new&lt;/span&gt; ArrayCollection&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;public&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;function&lt;/span&gt; MyRendererCache&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;  &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;super&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;           &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #b1b100;"&gt;for&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;(&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;var&lt;/span&gt; x : &lt;span style="color: #0066cc;"&gt;Number&lt;/span&gt; = &lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt;; x &lt;span style="color: #66cc66;"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color: #cc66cc;"&gt;20&lt;/span&gt;; x ++ &lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;cache.&lt;span style="color: #006600;"&gt;addItem&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;new&lt;/span&gt; MyRenderer&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;    &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0066cc;"&gt;public&lt;/span&gt; &lt;span style="color: #0066cc;"&gt;static&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;function&lt;/span&gt; getRenderer&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; : MyRenderer &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt; &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="font-weight: bold; color: #000000;"&gt;var&lt;/span&gt; renderer : MyRenderer;&amp;nbsp;  &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #b1b100;"&gt;if&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;(&lt;/span&gt; cache.&lt;span style="color: #0066cc;"&gt;length&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;&amp;lt;&lt;/span&gt;= &lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;&lt;/span&gt;　　　　 &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;renderer = &lt;span style="font-weight: bold; color: #000000;"&gt;new&lt;/span&gt; MyRenderer&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;    &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #b1b100;"&gt;else&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;         {&lt;/span&gt; renderer = cache.&lt;span style="color: #006600;"&gt;removeItemAt&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt; &lt;span style="color: #cc66cc;"&gt;0&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; as MyRenderer;    &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&amp;nbsp; &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #b1b100;"&gt;return&lt;/span&gt; renderer;        &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&amp;nbsp;      &amp;nbsp;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #0066cc;"&gt;public&lt;/span&gt; &lt;span style="color: #0066cc;"&gt;static&lt;/span&gt; &lt;span style="font-weight: bold; color: #000000;"&gt;function&lt;/span&gt; setRenderer&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt; renderer : MyRenderer &lt;span style="color: #66cc66;"&gt;)&lt;/span&gt; : &lt;span style="color: #0066cc;"&gt;void&lt;/span&gt; &lt;span style="color: #66cc66;"&gt;{&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;&lt;/span&gt;    cache.&lt;span style="color: #006600;"&gt;addItem&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;(&lt;/span&gt; renderer &lt;span style="color: #66cc66;"&gt;)&lt;/span&gt;;        &lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #66cc66;"&gt;&lt;/span&gt;&lt;span style="color: #66cc66;"&gt;}&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;在构造函数中，你操作缓存用最小数目的renderers，比如说2个。这个缓存有两个静态方法，getRenderer和setRenderer，第一个是来获得一个renderer，第二个是当结束时返还给它。这种方式下内存中renderers的数量可能增长超过最小的数目，但是仅是临时的，因为GC会在他们当不在被引用时删除他们。一个重要的问题是跟setRenderer有关，当你不再需要一个renderer时，你必须把它返回给cache，否则我们又陷入内存泄漏中，如上解释的那样。为了达到这个目的，我们来利用renderer的remove事件，remove事件是当一个UI元素被从显示列表中移除时被触发。例如当我们调用removeAllChildren()，这样的事件对于每一个renderer来说都会被触发。我们可以这样修改renderer：&lt;/p&gt;&#xD;
&lt;pre &gt;&lt;span style="color: #009900;"&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;lt;mx:VBox&lt;/span&gt; &lt;span style="color: #000066;"&gt;xmlns:mx&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"http://www.adobe.com/2006/mxml"&lt;/span&gt; &lt;/span&gt;&lt;span style="color: #009900;"&gt;    &lt;span style="color: #000066;"&gt;borderStyle&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"solid"&lt;/span&gt; &lt;span style="color: #000066;"&gt;width&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"200"&lt;/span&gt; &lt;/span&gt;&lt;span style="color: #009900;"&gt;    &lt;span style="color: #000066;"&gt;remove&lt;/span&gt;=&lt;span style="color: #ff0000;"&gt;"onRemove()"&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #009900;"&gt;    &lt;span style="font-weight: bold; color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;    private function onRemove():void {MyRendererCache.setRenderer(this);    }....&lt;span style="color: #009900;"&gt;&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;lt;/VBox&lt;span style="font-weight: bold; color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;如果现在来运行profiler，你会注意到，内存增长到一个给定的点并且保持稳定，如下图所示：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://spreadingfunkyness.com/wp-content/uploads/2009/01/memstable.gif" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;恭喜，你已经解决了内存泄漏！&lt;/p&gt;&#xD;
&lt;p&gt;建议性GC&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;除了偏向于自动的GC过程，adobe还允许程序员来建议干涉性的GC。这个命令在flash.system包中的System.gc()，通过这篇文章&amp;ldquo;强制垃圾回收过程&amp;rdquo;，但是在我的经验来看，这仅仅是一个模糊的干涉建议，它能解决某些情况，因此在开始时它值得一试，当你需要一个快速的方法来节省一些内存时。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1674192.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/02/26/1674192.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/sun11086/archive/2010/02/26/1674036.html</id><title type="text">[转] 两篇关于flash 职业和webgame的文章</title><summary type="text">第一篇转自:http://flashteam.tencent.com/post/52/诠释flash的职业发展道路/作为极少数的还活着的纯flash枯骨之一， 在经历了从mm到adobe，从as1到as3，从当年flash等同于动画的代名词，到当今的flash程序员大批的崛起的时代，一直想抽时间写一个职业发展总结来给新学习flash的，以及对于flash职业很模糊的同学同事同乡同人类们分享下这方面...</summary><published>2010-02-26T02:36:00Z</published><updated>2010-02-26T02:36:00Z</updated><author><name>sungo</name><uri>http://www.cnblogs.com/sun11086/</uri></author><link rel="alternate" href="http://www.cnblogs.com/sun11086/archive/2010/02/26/1674036.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/sun11086/archive/2010/02/26/1674036.html"/><content type="html">&lt;p&gt;第一篇转自:&lt;a href="http://flashteam.tencent.com/post/52/%E8%AF%A0%E9%87%8Aflash%E7%9A%84%E8%81%8C%E4%B8%9A%E5%8F%91%E5%B1%95%E9%81%93%E8%B7%AF/"&gt;http://flashteam.tencent.com/post/52/诠释flash的职业发展道路/&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;作为极少数的还活着的纯flash枯骨之一， 在经历了从mm到adobe，从as1到as3，从当年flash等同于动画的代名词，到当今的flash程序员大批的崛起的时代，一直想抽时间写一个职业发展总结来给新学习flash的，以及对于flash职业很模糊的同学同事同乡同人类们分享下这方面的心得，让大家少走一些弯路，能重新认识下flash技术和flash行业。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;首先，我是一个幸运的flash开发者，我所在的公司一直都把flash作为公司最主要的技术之一，所以我有机会从很早的时候就一直深入接触flash和相关技术并从事as开发职位以及相关职位的招聘。不过这在5，6年前来说，是很难找到这种公司的，那时中国市场依然普遍对flash不感冒，但是随着flash的普及以及flash游戏和网站项目的市场进化和发展，flash程序员现在有了很好的契机，很多新公司都有对flash人才重视起来，各种职位层出不穷，让热爱flash技术的人们有了很多更适合自己的选择。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;那么如何区分用人单位招你过去是否偏重于flash技术呢？很简单，从职位title的名字可以过滤多数，如UI Designer（UI设计师），网站设计师（很含糊的一个职位），软件工程师等。 这些职位描述多数也都包含flash，但却很少使用到flash，多数是让你作为一个技术备份，如果选择这类职位，将直接让你走出flash行业。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;那么让我们看看正规的flash行业内的圈子是怎样的：&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;a style="color: #000000; text-decoration: none; border-bottom-color: #ef0050; border-bottom-width: 1px; border-bottom-style: dotted; padding: 0px; margin: 0px;" href="http://flashteam.tencent.com/wp-content/uploads/2010/02/flashroad.jpg"&gt;&lt;img style="padding: 0px; margin: 0px; border: 0px initial initial;" height="422" width="670" src="http://flashteam.tencent.com/wp-content/uploads/2010/02/flashroad.jpg" title="flashroad"  /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;＃注：上图从左至右依次表明了flash职位的发展道路， 从上至下表明了从设计师到程序员的偏重度。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;在flash行业内&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;第一阶段：&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;当你刚学习flash时，无论你是作为设计师还是之前从事别的程序的程序员，都是一片空白，所以都在一个模糊混沌的起点，这个阶段统称为flash newbie（新手） 阶段，在这个阶段内，你会根据你自己的喜好，选择适合自己的技术，如设计师会偏重动画，motion graphics以及手绘，程序员会偏重as，网站编程和视觉特效，设计和程序都会一些的人学的就比较杂，各方面的技术都会搞一些，在第一阶段内我推荐尽量让自己多学习一些各方面flash技术，多发掘自己的综合潜力，这对你后面在职位选择时就多一些范围。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;第二阶段：&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;随着你对flash的逐步深入，你会发现自己的特长会被凸显，这时会有一些职位适合你入行&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;Flash Designer（&lt;/strong&gt;设计师）， 这个职位在以前很常见，是美工专职做flash的一个特殊职位，会一些简单的as，并且会画动画，做一些motion graphics，同时也会做一些平面设计。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;NewMedia Developer&lt;/strong&gt;（新媒体开发者），新媒体开发者的概念是公司需要综合能力的人才，需要会as，但不需要特别强，也要会做一些动画，拼装素材以及会写简单的js，通常是flash网站项目的公司多一些这类职位。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;Actionscript Programmer&lt;/strong&gt;（纯as开发），纯as开发者多见于程序员出身的背景，这两年比较多的java和javascript前端开发者加入了flash阵营，这个职位的个性就更加明显：完全不需要管界面，甚至有不会用flash ide的人，使用flex以及第三方编辑器直接运行flash项目，但这类人群对flash的综合技术认知不够，还需要时间深入了解flash，不能完全用java和js的想法开发flash项目，这个阶段的as开发者，暂时还没有显著的职业特性来区分。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;第三阶段：&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;慢慢的，随着经验的积累和对flash的了解深入，和公司项目需要，已经慢慢走出了flash的范畴，出现了三个更明显的职位：&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;Interactive Designer（互动设计师），&lt;/strong&gt;这个职位是因为设计师随着个人发展的喜好以及对于程序的了解深入而有的一个职位，广告公司这种职位多一些，除了会设计外，还需要你写一些程序，但偏向前端表现，如粒子特效和tween动画。这类职位并非一般意义上的交互设计师。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;Interactive Programmer （互动程序员）&lt;/strong&gt;，这个职位和上面的职位很类似，但是偏重点偏程序多一些，但平时的工作也会做一些动画，但可能是video（aftereffect），有时也会涉及到director lingo编程和网页js和flash小游戏，这个职位其实很累，需要会很多的技术，但是通常职业选择面会广一些。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;Game Programmer （游戏程序员）&lt;/strong&gt;，这个职位就在08年之前都很少见，而且是纯flash游戏开发，但这两年就随着sns游戏的普及以及webgame的投资增多就很抢手，导致现在看flash简历基本都说自己会写游戏。这个职位的基本需求其实很多人没有搞清楚，下面我略微详细的说下以便大家能多补充下知识。 首先你要&lt;strong&gt;热爱游戏&lt;/strong&gt;，如果你不爱玩游戏那么你也开发不出什么好体验的游戏。技术方面还要会很综合的各种游戏算法，如A*,各种排序，数据结构，地图技术以及需要你对性能优化有一定的经验，如知道矢量图和位图在flash中运行时的差异，地图的按需加载，如何写程序才更有效率（苛刻到毫秒级微秒级）等，并且需要一定的设计模式知识，如果是3d项目，还需要有一定的3d知识，还需要对客户端服务器端传输有一定的优化经验，客户端安全性，防外挂以及协议安全等，如果是海量服务还需要针对流量优化。 所以想要成为一个真正的flash游戏程序员，你背负着n多需要挑战的使命（不归路？），但如果你有一颗热爱游戏的心，上面所列的各种技术都会迎刃而解，会慢慢兴趣式的攻破，所以这也是为什么我把热爱游戏放到首要条件之一。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;就这样慢慢走出了flash&amp;hellip;&amp;hellip;&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;进入到了第四阶段，也是你flash职业生涯的黄金时段&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;这时因为你在flash之路所接触到的经验，已经不在拘泥于flash了，但仍然以flash项目为主。当然如果你选择了转行，就不是本文所谈论的范畴了。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;黄金阶段里面所出现的几个职位是这样的：&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;交互设计后，通常其实直接进入到了art director/newmedia director，但本文没有画出这两个职位。这里是一个发展瓶颈，交互设计师、程序员走到了这里已经在业界有了一定的资历和名气，也就自然走出了flash，万精油类型的发展适合开一些studio和广告公司合作，做单子或在一个大一些的公司做director走管理路线长期发展。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;如果对管理路线不感冒，下面还有更深入的&amp;rdquo;职位&amp;ldquo;，这些职位可能你在市场上看不到，但能进入到此，你也是能独当一面的超级flash人才了：&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;3D Programmer&lt;/strong&gt;，这个职位现在还不多，但是随着硬件以及flash技术的发展，这个职位也许在未来会火起来，也是游戏开发者的一个比较好的进阶选择，偏重于图形学和前端表现多一些。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;Architecture&lt;/strong&gt;，构架师，随着经验的积累以及对设计模式等框架技术的深入发掘，一个flash开发者最终会把自己定位成构架师，框架设计师，通常有一些企业型项目需要这类人才来建造项目框架，学过java的人很容易的走进这里，相当于在flash之路中仅仅是个过路人。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;Evangelism&lt;/strong&gt;，flash传教士，这个其实不算一个真正意义的职位，是一类人群，早期是积极推广flash技术，并有影响力的一批外国人，如flashguru，gskinner等。这类人群的技术其实很全面，前后端技术都会懂一些，但深浅不一，对flash技术也很痴迷，能够对业界产生影响。这类人群在中国现在依然比较少，希望多一些技术全面的中国flash开发者能发扬此类精神弘扬flash文化。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;说了这么多，也许有人会问，楼主是哪类人呢？&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;其实我的路非常曲折，在上图中窜梭不同职位多次，否则也很难有这么多感慨，呵呵。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;最后，希望此文能对热爱flash的你有帮助，祝你们在flash的职业生涯中一帆风顺。&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;第二篇转自:&lt;a href="http://bbs.blueidea.com/thread-2969949-1-1.html"&gt;http://bbs.blueidea.com/thread-2969949-1-1.html&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;★我的FLASH WEB GAME开发历程&lt;/strong&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;2007年的夏天，顶着炎炎烈日，我从学校直接跑到上海，开始了我的FLASH WEB GAME创业之旅。时至今日，转眼快三年了。作为国内比较早的一批FLASH WEB GAME开发人员，今天我粗略的总结一下这两年多的经验和心得。讲的不对的地方，请大家多多指教。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;2007年刚到上海的时候，初创团队只有四个人，一个CTO,一个美术，一个后台，一个前台。手里的产品是一个已经在台湾运行三年左右的FLASH社区，和国内的梦境非常像。这个产品还是不错的，早在FLASH5就在开发出来了，FLASH6出来后，又用新版本的AS1重写过。这个产品让我又爱又恨，爱的是，在2007年的时候，国内除了梦境和1D真的很少有能赶上它的；恨的是，这个产品竟然没有前端源码！要想修改还要破解！玩过AS1，在时间轴、MC和BTN上写过代码的朋友应该知道这是什么概念&amp;mdash;&amp;mdash;1个字：囧！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;后来老板可能也觉得这样改下去不是办法，终于同意自己重写一个。正好07年有条新闻很火爆：国外有个FLASH社区第一次利用FLASH技术取得了重大成功，以7亿美金卖给迪斯尼，它就是&amp;ldquo;企鹅俱乐部&amp;rdquo;。老板看到了商机，我们决定做一个中国版的企鹅，于是&amp;ldquo;海底世界&amp;rdquo;应运而生了。而&amp;ldquo;海底世界&amp;rdquo;的创意，只不过是我们四个初创成员在闲聊时，我开玩笑随便说的。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;海底世界正式开发到现在差不多正好两年，期间我们碰到无数的问题和困难，不管是公司层面或技术层面，都是如此，但始终是坚持了下来。产品一天天完善，公司规模也一天天扩大。前端从最开始的两个人，到现在5个人；后端从最开始的FMS+PHP到现在自己写的socket服务器；公司规模也从最开始的4个人，到现在的50多个人。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;strong&gt;★当今FLASH WEB GAME概述&lt;/strong&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;2007：含苞欲放！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;2007年可以说是FLASH WEB GAME发展史上的分水岭。2007年之前，我们眼里只有梦境，最多再加上昙花一现的抱抱城，那时候根本没有&amp;ldquo;FLASH WEB GAME&amp;rdquo;这个概念，大家谈的都是&amp;ldquo;FLASH社区&amp;rdquo;，&amp;ldquo;FLASH社区&amp;rdquo;这个词在很长一段时间代表着FLASH应用领域的至高点。也许2007年已经有不少团队开始研发FLASH的MMORPG了，我曾经有幸知道几个，但很可惜，不少都胎死腹中，2007年国内在线上运营的FLASH WEB GAME基本上还是空白。但不管怎么说，我相信2007年是蓄势待发的一年，肯定有很多类似我们公司的团队，在默默的努力着。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;2008年：雨后春笋！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;经过2007年的积累和准备，FLASH WEB GAME业界的战斗终于在2008年打响，以&amp;ldquo;摩尔庄园&amp;rdquo;，&amp;ldquo;海底世界&amp;rdquo;为代表的&amp;ldquo;FLASH儿童虚拟社区&amp;rdquo;开始崭露头角；以&amp;ldquo;纵横天下&amp;rdquo;为代表的FLASH策略类游戏兴起；以&amp;ldquo;昆仑&amp;rdquo;为代表的FLASH&amp;nbsp;&amp;nbsp;MMORPG让&amp;ldquo;无端网游&amp;rdquo;的概念又炒了起来。还有各种基于FLASH的卡牌对战类，联机棋牌类，模拟经营类游戏等等，都如雨后春笋般破土而出。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;2009年：百花齐放！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;2008年，国内虽然一下出了很多FLASH WEB GAME,但大家只要认真收集，总归还是能数的过来，可到了2009年，几乎每隔一个月，都会有几个新的FLASH WEB GAME进入大家视野，而且他们越来越完善，功能越来越强大，盈利模式也开始成熟并多样化。2007年每出一个FLASH WEB GAME,我都会为之兴奋，并很有兴趣的去研究它。而到了2009年末的时候，FLASH WEB GAME已经多到我连体验的兴趣都没了，我已经彻底搞不清楚国内到底有多少个FLASH WEB GAME在运营。而伴随着SNS行业的成熟，基于SNS的Social game进一步扩大和模糊着FLASH WEB GAME的概念。FLASH在游戏领域里的应用，在经历了&amp;ldquo;社区&amp;rdquo;、&amp;ldquo;策略类&amp;rdquo;、&amp;ldquo;MMORPG&amp;rdquo;后，发展到今天创意无限，精彩纷呈的&amp;ldquo;Social game&amp;rdquo;，已经很难用一个词，根据游戏类型概括所有的FLASH应用了。所以我觉得&amp;ldquo;FLASH WEB GAME&amp;rdquo;，也就是&amp;ldquo;FLASH网页游戏&amp;rdquo;这个词还是相对最恰当的，这也是我前面一直使用这个词的原因。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;2010年 &amp;ndash; 2011年：胜者为王！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;就像春秋战国时期，在经历过&amp;ldquo;百家争鸣&amp;rdquo;后，必然是&amp;ldquo;天下一统&amp;rdquo;。随着游戏巨头和互联网大亨对网页游戏的逐渐重视，以及政府的介入，还有最早领跑某些领域的创业公司不断壮大，相信在不久的将来，网页游戏领域也会出现几个真正的领袖。别的领域不敢说，在我们儿童市场这块儿，淘米公司已经逐渐呈现一家独大的趋势，不信的话，你可以随便找几个小学生问问，比如你父母辈亲戚朋友的孩子，问他们是否知道摩尔庄园和赛尔号，是否充值了，相信你会得到非常惊讶的答案。所以，2010年后，任何小作坊型的创业团队再想进入FLASH WEB GAME行业，都需要更加谨慎了！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;strong&gt;★创业型游戏公司面临的问题和困难&lt;/strong&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;在正式进入FLASH WEB GAME的技术探讨前，我左思右想，还是觉得必须先说一下创业公司存在的问题和困难，为后面可能不太&amp;ldquo;正规&amp;rdquo;的做法找一个合适的&amp;ldquo;理由&amp;rdquo;。&amp;mdash;&amp;mdash;人不能太爱找客观理由，但也绝对不能为了避免&amp;ldquo;找理由&amp;rdquo;之嫌，而弃客观现实于不顾，毛爷爷曾告诫我们要懂得&amp;ldquo;实事求是&amp;rdquo;。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;任何有过创业经验的技术团队和公司应该都知道，教科书那套从成功公司抽象出来的模式在创业初期几乎只能是神话一般的存在，相信没有几个公司能完全做到。当然那种千万级启动资金，有成功背景的新公司除外。像我们公司，一开始就4个人，前台和后台各一个人，如果我们两个都每天用一半时间考虑架构和写文档，我们的产品猴年马月也上不了线了，况且我们写了给谁看呢？在这个阶段最最重要的目标就是尽快把产品做出来，上线运营出一定效果，给产品更加明确的方向，给团队信心，然后尽最大努力去融资，以求下一阶段的发展。产品出不来，只靠一个idea和产品策划书就想找投资的时代早就一去不复返了。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;我觉得一个创业公司最现实的发展观应该是这样的：&lt;strong&gt;初创阶段（技术导向型阶段）&lt;/strong&gt;：这个阶段要一切以&amp;ldquo;我们能做什么&amp;rdquo;为基础，在财力、人力、经验都不足的情况下，找出我们的优势，&amp;ldquo;把我们所擅长的做到最好&amp;rdquo;是我们唯一的筹码，毕竟初创人员能走到一起，必然是有一定共识，在某方面有优势的。而&amp;ldquo;我们能做什么&amp;rdquo;，在初创阶段很大程度上就是指技术能做什么。没钱、没人还想把项目做的又快又好，绝对是痴心妄想。这个阶段就开始叫嚣&amp;ldquo;市场主导产品&amp;rdquo;，&amp;ldquo;不看过程只看结果&amp;rdquo;等口号，完全是不务实的态度，市场上最热门的产品你未必能开发出来，创业阶段，前途未卜，你不看过程看什么？&lt;strong&gt;发展阶段（人力导向型阶段）&lt;/strong&gt;：假设我们顺利度过了第一阶段，公司开始有现金流或者找到了天使投资，我们就开始布置进一步的发展了，这个阶段招人将是公司的一个要务，招有创业精神的人，更要招我们需要和缺少的人。以前我们公司只有AS，于是游戏server只能用FMS，现在应该招一个C++ socket的人了；以前公司没有网页前端，网站都是原画和PHP代劳的，现在该弥补了；以前整个游戏都是架构师们设计并实现的，现在应该招一两个做模块打下手的人了。这个阶段虽然不适合大规模扩展人手，但在要害人力点上，也绝对不能抠门，我们公司就是吃亏在socket上，公司一直不肯招一个专业写server端的，一直让前端和PHP代劳，结果游戏同时在线人数一超过5000就会出各种离奇问题，最恐怖是大家都不清楚问题到底在哪里，只能大眼瞪小眼，这个时候老板就会臭骂公司这帮技术都是饭桶，这么多人还搞不定这个问题。老板不懂技术，说出这样的话无可厚非，但老板不听劝，死活不愿意招要害人员，这就是他的错了。总之这个阶段要以人力发展为核心，尽最大的努力把必要的人手配备齐。必须注意的是，这个阶段不适合空降部门领导，公司发展阶段，只有初创人员陪公司一路走来，最明白公司的问题，以及各种问题的根源。而空降的领导容易只看到问题，不明白为什么会有问题，有时候难免说出&amp;ldquo;道理上很正确，但实际上不可行&amp;rdquo;的话，而老板为了配合新领导树立威信，很多时候不得不偏向新领导，这样以来很容易打击到初创人员的积极性。更严重的是可能让初创人员看不到前途，创业的激情沦为打工的无味。这个阶段挖墙脚空降领导，希望他们能把公司制度正规化，希望他们拯救公司的做法可能适得其反！公司初创人员这时候应该依旧是公司的顶梁柱！&lt;strong&gt;成熟阶段（产品导向型阶段）&lt;/strong&gt;：如果有幸过了前两个阶段，到了这个阶段的时候，公司应该已经实现了正向盈利，作为一个游戏公司，一旦靠自己实现盈利，相信各种投资机构肯定会主动找上门，千万美元的投资绝对不夸张，你将会为到底接受哪家的投资而烦恼。人力、财力、物力都不再是问题，产品研发和运营的经验也成熟了，这时候唯一要关注的就是市场，什么样的产品更被市场和用户接受，争取开发出更多更好的产品。产品要多样化，公司要规模化，要形成自己的产品链和平台，抓住更多的用户，开拓更多的盈利模式。这时候才是产品主导公司，才是从大公司挖人的时代。如果这些都做到了，当老板再次开会谈&amp;ldquo;上市&amp;rdquo;的问题时，每个人脸上将会笑容依旧，只不过初创阶段的笑容是那种开玩笑试的玩世不恭，而现在则是对未来的美好憧憬。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;其实任何理论都是有前提的，牛顿定律也只是在低于光速的情况下才适用。公司发展的历程中，老板和员工肯定都会有其信仰和观念，都会用各种言辞来说服别人。但我相信没有那种理论和言辞是永远正确的，尤其是书上和大公司的那些所谓的成功经验更是要警惕，因为它们身上有太多的光环，一场本来可能很有价值的讨论，说不定就会被一句&amp;ldquo;盛大就是这么做的&amp;rdquo;给结束掉！所以在我们谈任何理论的时候，不妨看看公司现在所处的阶段，不妨时刻谨记毛爷爷的话，实事求是的看待自己。我们公司就曾屡次吃类似的亏，公司在第一阶段刚拿到天使投资，就想做第三阶段的事了，结果做了很多，一件也没做好，白白浪费了很多时间和大好机遇。其实当时老板用来说服人的理论也都是正确的，只不过不适合公司的实际发展情况而已。还有一点要强调的是，不管公司现在处于第几阶段，坚决不能全盘否定其它阶段的付出和努力以及很多不得不犯的&amp;ldquo;错误&amp;rdquo;。之所以强调这一点，也是我们公司曾踩过的雷区，当我们发展到第二阶段的时候，公司就开始忙着空降领导，然后这些领导对我们之前的做法开始逐一否定，把做后台的哥们儿说的一无是处，搞得团队气氛极不融洽，吵架红脸的情况经常发生。这就好比我党在经历了长征、抗战和解放战争的原始积累后，在最终发动三大战役攻打大城市时，指着毛爷爷的鼻子说：&amp;ldquo;你以前那套只敢打农村，打的过就打，打不过就跑的逃跑主义路线完全是错误的！&amp;rdquo;试想，如果党内空降领导都是这种态度的话，将会对我们党和战士们的积极性产生多大的打击！这种情况其实在长征途中就发生过，差点就葬送了党，好在遵义会议及时纠正了苏联空降回来的王明等人的左倾激进主义，挽救了党。而我们的公司，谁来挽救我们的公司呢！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;strong&gt;★FLASH WEB GAME的系统架构&lt;/strong&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;我在这里把一款FLASH WEB GAME的架构分为三部分：系统架构、前端架构、后端架构。&amp;ldquo;系统架构&amp;rdquo;主要是指根据一款游戏的特点以及公司的实际情况选择合适的技术实现方案，主要包括美术方案，前端方案和后端方案；&amp;ldquo;前端架构&amp;rdquo;主要指FLASH前端的主程序以及模块划分；&amp;ldquo;后端架构&amp;rdquo;主要指即时通讯部分和数据库。这章先谈系统架构。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;谈到架构，我不得不说，那些所谓的完美架构，能够一次架构好，永远不用改的说法只能是传说，或者技术人员忽悠老板的说法，对于创业公司更是如此。创业公司初创时期更多的时候需要在游泳中学会游泳，因为大家都没有经验，失败是最好的教科书。就算大家知道应该怎么做，很多时候条件也不允许。比如我们在一开始就知道应该自己写socket服务器，可就是没socket的人才，于是不得不先使用FMS+PHP。公司一开始的美术更精通FLASH一些，而且我们计划的是要做&amp;ldquo;企鹅&amp;rdquo;，于是我们选用矢量图。可后来随着公司产品定位的不断改变，我们的架构和解决方案也会不断调整，当达到一个临界点时，修改的代价已经超过重新开发，我们就不得不对架构进行&amp;ldquo;重构&amp;rdquo;了！这时候聪明的老板应该支持程序员们的意见，充分调动他们的积极性尽快改完，全公司应全力配合，尽快度过难关。而不明事理的老板肯定会每天抱怨程序员无能，搭出一个垃圾架构不能满足产品的持续快速发展，拖了产品和市场的后腿，给程序员造成很大的压力，积极性没了不说，在长期经验积累之后本来可能是一次非常好的机会能做出一个相对完美的架构，满足日后很长一段时间的需求变更，结果因为老板过分催促和施压，又烙下了许多隐患，而这些欠下的债，总有一天要还的，这一天来临之时，责任虽然可以完全由程序员承担，但整个公司都要为之付出代价！所以关键时刻程序员该坚持还是要坚持自己的观点，要尽量说服老板，程序员的社交能力在这个时候就凸显作用了，你要明白你不但是在对自己负责，也是对公司负责！另外，真的很希望天下的老板们都能明白一个道理：能够根据公司实际情况不断调整的程序员才是最可爱最辛苦的程序员，而不是那些什么都不管，上去就提一大堆要求，必须都满足他，他才愿意做的程序员。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;就算时至今日，FLASH WEB GAME在国内发展差不多三年了，但我敢说FLASH WEB GAME还是没有什么行业标准的技术解决方案，尤其是前端，大家都是自成一派。在这个时候，让我们再次搬出那句老话：不管黑猫白猫，抓住老鼠的就是好猫。不过经过这几年的摸索，还是有一些规律可循的：&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;1，美术：如果游戏画面简单，色彩构成相对单一，场景内总体元件能控制在100个以下，则非常适合直接使用矢量图，画面各组成部分尽量拆分为能重用的独立元件。这样虽然牺牲了客户端的CPU，但能因为重用最大化而大大减少美术的工作量，也方便他们日后应对需求变更，比如某些元件的尺寸变动。在画面简单，元件又少的情况下，利用递归全元件位图缓存，拿少量内存还能换回大量CPU，找出这个平衡点，完全可以做出很好的用户体验。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;可大部分时间，我们的游戏场景可能都非常炫，画面复杂，色彩鲜艳。使用矢量图的话，一方面不容易画出想要的效果和精细度，这时候使用矢量图反而增加了美术的工作量和难度；另一方面，使用矢量图还有可能导致客户端CPU严重飙升，超出普通客户端电脑的承受范围。这时候我们应当用位图做游戏背景，重用性不大的元件要尽量合并到背景位图里，减少位图总个数，一些简单的动画如果非要用FLASH做成矢量动画的话，也要尽量做成逐帧的，相信FLASH IDE玩的转的美术同志们应该知道怎么把一个渐变动画瞬间转换成逐帧动画。逐帧动画虽然会导致SWF文件体积增大，但相对于换回来的客户端CPU来说还是值得，这其实是牺牲了一些服务器带宽和用户等待时间，换回严重的客户端CPU超载。而如果你的动画非常复杂和精细，精细到只有AE等粒子特效软件才能表达的话，建议还是直接从AE里导出位图序列，在FLASH里弄成逐帧动画，太过复杂的动画绝对不能用FLASH直接做，不但很难做出想要的效果，而且复杂矢量图的SWF文件体积也会大大超过位图，有可能导致用户因为SWF文件加载时间过长，失去等待的耐心，这时候我们情愿牺牲美术的工作量和工作流程，换回想要的效果，减小SWF文件体积。还有一点要提醒的，时间轴动画不可见时，程序一定要记得将其stop掉，不像程序动画，时间轴动画不可见时，FP内部其实依旧在重绘，对CPU还是有影响的。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;还有一种极端情况是场景元件超标，比如整个游戏内所有元素（包括各种MC、BTN、位图以及程序创建的displayObject，总量超过500，这时候你会发现，画面静止还好，但只要游戏上鼠标随便一晃，或者有几个人物随便走一下路，CPU都会狂飙，就算这500个元件都是位图也无济于事。其实这是FLASH的一个瓶颈所在，是目前所有FLASH大型项目都有可能碰到的问题，也是我觉得阻碍FLASH进一步发展的主要障碍之一。在一个元件超多的背景图上进行任何的鼠标动作、动画、文本渲染，都会导致CPU严重飙升，甚至画面很卡。要解决这个问题，本质的也是唯一的方案就是减少元件数量，要想尽一切办法降到200以下。而这需要美术、前端和策划通力合作才行，绝对不是前端程序员就能搞定的事。策划要从产品的角度上看能不能简化目前场景同一时间出现的元素，美术要把能合并成一张图的元件在绘图软件中合并成一张位图，前端AS程序要把不需要响应鼠标事件的元件的mouseEnable和mouseChildren都设置成false，一些能利用copyPixels合并的位图就合并成一张，比如可以平铺创建的房间地板和墙面，要copyPixels成一张图，而不是new出好几百个元件。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;其实元件超标的情况是大多数没有经验的团队很容易发生的问题，这时候前端程序员要起到领头羊的作用，给大家讲明白道理，用事实让大家信服，组织大家一起把事情做的更好，而不是一味的在那里抱怨FP效率低。因为这时候你是团队唯一可以依靠的人，如果这个问题解决不了，虽然大家都有责任，但前端毫无疑问是罪魁祸首！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;极端情况下的极端解决方案：如果游戏策划的非常酷，一个子弹爆炸效果就需要几十个元件支撑，画面上同时又需要几十个坦克混战，这时候常规的解决方案是根本达不到的，但不是说就一定无法做了，你可以利用强大的BitmapData类把每帧要显示的游戏画面完全计算好并且在内存中绘制，然后以一张图的方式渲染给用户，这时候用户玩你的游戏仿佛就像在看逐帧的动画，此时FP占用的CPU大部分都是计算耗用的，而不是渲染耗用的。其实AS的执行效率远远高于屏幕渲染，你把CPU的主要负荷转移给AS，反而能做更多更炫的事情。据我的初步研究，前段时间名噪一时的FLASH版3D雷神，还有现在很多国外效率高的&amp;ldquo;有点假&amp;rdquo;的TD类和飞机类单机游戏都是这么做的。可这种模式适合用来做多人联机并且有大量交互界面的FLASH WEB GAME么？我初步思考了一下，感觉是不可能的。首先，大量的交互界面意味着需要用鼠标点击，试想在一个逐帧动画中，每帧都要响应鼠标是什么概念？所以UI部分首先排除了；然后是大量的即时数据交互，每当一个异步的请求得到响应，画面就需要做出相应的改变，这将对本来还可能比较工整的内部绘制算法制造非常大的麻烦，难度太高！基本上也不可行；最后是很多FLASH WEB GAME的画面重用性并不是很高，比如像我们游戏的每个场景都是美术专门画的，而不是用地图编辑器编辑的，这就意味着你无法完全用程序拼出一个场景来；综上我觉得一个款FLASH WEB GAME基本不可能完全使用copyPixels完成，最多是部分实现，比如我上面说的墙面和地板。除非你的游戏策划很NB，知道什么游戏能最大限度的利用copyPixels，而这样的策划估计本身肯定也是个前端程序员。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;2，前端：从系统架构的角度上讲，前端其实很简单。现在WEB GAME主流的前端技术无非就是AS和JS。JS的前端地位其实比AS要老，很多人的JS经过这么长时间的磨练，功力深厚，做一个策略类甚至简单的MMORPG都没问题。但现在用AS来做的话可能更简单，更容易做出更酷的效果和更好的用户体验。所以最近两三年，随着基于面向对象的AS3逐渐完善和普及，FLASH WEB GAME似乎逐渐成了唯一的主流。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;其实除了as和js外，还有很多前端技术可以供我们选择，比如shockwave，java，还有那传说中的flash killer：silverlight和html5等等。每种技术都有其优劣势，比如shockwave在图形渲染方面比flash强了千百倍啊千百倍，因为它可以完全调用显卡，我在网页上玩过一个基于shockwave的CS，流畅度和操作感完全不亚于桌面版的CS，还有国外的哈宝以及国内的娜娜米米都是基于shockwave的。而Java和silverlight也都有强大的背景，HTML5最近也是来势汹汹。但不管怎么样，2010年，FLASH仍以其广泛的覆盖率、酷炫的效果和逐渐成熟的开发社区，以最高的综合评分独领WEB GAME业界风骚。所以任何公司和团队，如果现在想做WEB GAME的话，如果实际情况允许，FLASH还是最好的选择。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;3，后端：后端不是我的强项，我就不多说了，我只根据我们公司的经验谈谈心得。我同意前后端编程有很大区别，但绝不同意前后端谁简单谁复杂之说。根据我这几年的观察，我发现，前端偏重的是效果，是用户体验和细节处理，有时候可能还要涉及一些图形算法；而后端则偏重数据结构和数据处理，讲究的是性能、安全和扩展性。前端工作量一般比后端大，而后端需要的工作经验比前端多，想依靠一个只掌握了理论知识的大学毕业生就支撑一个公司的后端架构是严重不靠谱的！前端架构师必须是一个编程高手，十几、几十万行代码要在他的手里安排的井然有序，后端架构师则必须有过大型项目经验，并且项目同时在线人数达到过一定规模。前端架构出现问题，会严重拖垮开发周期，而后端架构一旦出现问题，对公司将是致命性打击。所以在公司里宣传所谓前端重要还是后端重要的说法，是完全错误的，任何一款好的产品，必将是策划、美术、前端、后端都达标的产品，缺失任何一块儿，都成功不了！不同部门之间的比较和较真儿没有任何正面影响！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;至于后端的技术解决方案，我感觉如果是需要大量即时交互，并且对即时性要求很高的游戏，就必须使用socket服务器。而如果对即时性要求不高，完全可以用PHP，部分的即时交互可以用socket实现或者HTTP轮询也可以。如果你的公司也像我们一样刚开始没有合适的C或者JAVA socket程序员，选择fms和sfs也未尝不可，这样至少可以让前端人员代劳，让项目可以启动。切记这只是为解燃眉之急的下下策，长久不了，公司要想办法尽快找到一个合适的人，在合适的时机重构。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;strong&gt;★FLASH WEB GAME的前端架构与人事分工&lt;/strong&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;前端的主程序架构和模块划分与人手和人事分工是紧密联系在一起的，而这些很大程度上又是由项目本身决定的。纵观现在国内绝大多数FLASH WEB GAME的规模和难度，我觉得前端AS人员大概需要2-7个之间，主程序有效代码一般不会超过10W行。在这种情况下，人事分工应当以功能和模块进行划分，尽量避免多人维护同一份代码，每个人各司其职，减少维护和协作的成本。这种模式非常适合人手不够，制度不健全，而且追求效率的初创公司。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;根据各种游戏类型的不同，分工也应该不同。策略类更注重界面开发，分工上应该向UI偏重，MMORPG类注重主架构一些，而像我们的海底世界，是更新驱动类社区游戏，每周都要发布新内容，还需要大量的小游戏和场景功能支撑，所以需要更多的模块和小游戏程序员。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;下面就以我们公司为例详细谈一下，我们公司最多的时候，一共5个AS程序员，分工是这样的：1个主架构，1个主UI,1个小游戏，2个场景和模块程序员。主架构同时负责FMS的sever端；主UI同时负责前端人员管理和文件管理；小游戏人员以平均每月两个单机或者联机游戏的速度循环不停开发，是相对最独立的一部分；而两个模块程序员，负责每周发布的新场景和新模块功能，他们的工作量其实蛮大的。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;先谈前端主架构，前端程序主架构有两个主要任务：1，要从架构高度合理划分前端各模块，提出可行的实现方案；2，从AS级别搭建程序架构（非文档级别），制定前端编程规则和接口，规范程序各部分的职责划分。这两个任务其实包括很多具体工作，比如：游戏启动流程制定，确定哪些SWF文件需要外部加载，那些功能可以从主程序剥离出去单独实现，前端配置文件怎么处理，公共素材怎么处理，MVC三层怎么划分，主程序框架的选定，主程序怎么和后台通讯，主程序如何与模块协作，哪些代码应该放在主程序中，哪些代码应该放在模块里，主程序如何既能提供模块所需要的一切功能和数据，同时又相对模块自我保护等等等等。其实我谈的还只是一些大的方面，具体到实现的级别，还有大量细节工作要做。而这些工作在项目启动之初都是非常重要的，直接影响到项目中后期的开发和维护效率。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;上面提到的那些点，我不可能全讲一遍，不然就不叫&amp;ldquo;浅谈FLASH WEB GAME&amp;rdquo;了！我只挑两个比较核心的内容跟大家略做探讨，就是前端AS框架和模块划分的问题。先谈前端框架：现在市面上流行很多前端框架，不管是针对&amp;ldquo;FLASH&amp;rdquo;的，&amp;ldquo;FLEX&amp;rdquo;的还是&amp;ldquo;通用的&amp;rdquo;都有。我们是否一定需要框架，或者必须使用某个框架，这完全是仁者见仁智者见智的事，从最终的结果上讲，争论这个问题意义不大，我相信一个5W行左右的项目，任何有5年以上编程经验的人，不管用什么作战策略，最终都能攻下山头，把项目做出来。但有一点至关重要：你必须能完全把握你的架构和你使用的框架，并能跟你的前端同事解释清楚。那好坏架构的区别在哪里呢？区别在于好的架构在开发过程中会更轻松，你不用天天担心的你代码，不用每天不停的写文档，以防止自己忘了复杂的逻辑，你可以在任何时间开始写代码，在任何时间去玩会儿游戏然后回来接着写；区别在于好的架构更符合业界标准，更容易被传统和正统的程序员接受理解；区别在于你可以用很简单的几句话就把你的架构思想描述清楚，用几个很简单的文档就能让别人接手你的代码，在人事变动和工作交接的时候让自己更轻松；区别在于当你掌握了一种通用框架或者自己总结一套成熟的架构后，你几乎可以套用以后的大部分项目，并不断完善它，开发越来越轻松，速度却越来越快！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;我们的项目，主程序使用的是pureMVC框架，而主UI部分是自己写的。主程序和主UI相互独立，可以单独编译测试。主程序是纯代码，用FLEX SDK编译，而主UI则是界面和AS混写并用FLASH编译。这样就把MVC中的V从物理层面上完全独立了。pureMVC框架正如其名字，是一款&amp;ldquo;纯粹&amp;rdquo;的MVC框架，在我看来，他只是帮我们实现了MVC的编程思想和套路，其它多余的功能一点没有，这使它具有更高的通用性，也是它最可爱的地方。根据我们的经验，pureMVC单核心版就已经完全可以应对主程序有效代码在10W行以下的项目了。但在我跟很多没有用过框架的前端朋友聊天中，发现他们对这些框架本身就有抵触心理，或者有些对MVC模式都理解的不深刻，用起MVC框架又怎能得心应手？还有一些更过分的朋友把自己的问题也归结到框架上，说什么用了pureMVC框架后，自己的项目编译一下要十几分钟，我听了之后哭笑不得，项目编译慢一般是因为没有合理划分模块导致主程序过大才导致的，跟框架有什么关系？如果因为大家的种种误解和这些人的言论而导致一些新人错过学习这么一款优秀的框架，我觉得实为憾事！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;pureMVC既然是一种MVC框架，这就意味着你首先要熟悉MVC。这种熟悉绝对不是对MVC的直译：模型、视图、控制器，而是要真正理解为什么要把程序划分成这几部分，在划分主程序模块时，要时刻能站在MVC的角度考虑问题，而当面对一段实际的代码时，能快速准确的判断，这段代码应该放在MVC中的哪部分。《pureMVC最佳实践》这份短短几十页的文档中，可以说处处闪烁着MVC的思想火花，不但清楚地阐述了怎么使用框架，而且时刻从MVC的角度告诉我们应该把哪些逻辑放在哪些部分中，应该注意什么问题。这个文档早已经有中文版，有兴趣的朋友可以自己去看看，文中有的，我这里就不赘述了。我只结合自己的体验谈一些文中可能没有涉及的，也是在真正开发中才会碰到的问题。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;1，模型部分在实际开发中除了存储数据，还有其他作用么？是的，其实它的实际职责非常多。它要给Command和Mediator提供接口，响应用户操作，进行数据操作或者请求远程数据服务，进行数据的序列化和反序列化，得到异步数据后可能还要检查数据合法化。但不管怎么样，它始终是在和数据打交道，同时也应该是你的主程序中唯一可以直接和数据打交道的管道，别的部分要想和数据有接触，首先要问问它同意不同意。模型处理完数据会以Notification的消息方式通知Command或者Mediator。但绝对不能在Proxy中直接调用Mediator，这是为了保证数据层的独立性、可移植性和重用性，也简化了你的架构思想。不过可移植性这个优势，估计很多搞FLASH WEB GAME的朋友暂时都没啥机会体验，呵呵。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;2，Command，Command，Command！连叫三声&amp;ldquo;Command&amp;rdquo;，希望可以引起大家的注意。因为Command的使用，在很大程度上反映着你对pureMVC框架的理解，甚至是对MVC模式的理解深度。在pureMVC框架中，各部分通讯是用Notification消息，Proxy可以给Command和Mediator发消息，Command可以给Command和Mediator发消息，Mediator可以给Command和Mediator发消息，怎么样？你现在是不是点晕了，这是正常的，其实我也有点晕！当你代码写到一定规模后，你会更晕。其实pureMVC框架这么设计本来是为了让MVC各部分尽量脱耦，但这带来一个负面情况就是消息发送与接收机制设计的太灵活了，灵活对小项目是好事，但对大项目来说，往往意味着混乱，甚至会导致灾难。那怎么办呢？只能靠我们的自觉性自我约束，简化架构思想了。根据《pureMVC最佳实践》中的建议，我的做法是这样的，尽量使用Command，让Command成为Mediator与Proxy之间通讯的唯一桥梁，Mediator和Proxy中发出的Notification，接收者一定是某个Command，然后再由Command处理并将结果转发给真正的消息接收者，Command就算仅仅起一个转发作用，仅仅有不到10行代码，也要创建一个Command类。这样不仅使你的架构更加清晰，而且也更符合MVC思想，Command类的大量存在还使你架构的业务逻辑具有了更好的封装性和扩展性，可谓是一箭三雕，何乐而不为？唯一的负面影响可能是你需要创建和维护更多的Command类文件，但相对于优势而言，这点影响不算啥。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;3，我知道现在可能还有一些朋友在用FLASH IDE写代码，这些朋友的执着让人钦佩，但我想任何一个熟练使用过FLEX BUDIER、FD或者FDT的朋友，都绝不会再回头使用FLASH IDE写代码了。&amp;mdash;&amp;mdash;不对啊？不是谈pureMVC的么？怎么扯到IDE上去了？这是因为我现在要讨论的问题就和IDE有关，假如你现在用的还是FLASH IDE的话，除了随时写文档外，我真的很难想出一个很好的方案可以让你在没文档支撑的情况下，轻松掌握和随时维护几万行代码。可如果你使用的是FDT,就可以在没有文档的情况下，利用&amp;ldquo;ctrl + r&amp;rdquo;和&amp;ldquo;ctrl + 鼠标左键&amp;rdquo;，以及全文件搜索等工具，瞬间搞清楚代码之间的联系和逻辑，找出要修改的地方。OK，终于到pureMVC了。如果你使用的是FDT,并且开始尝试使用pureMVC框架，可在使用的过程中，你发现你在写主程序时，还是不停的使用&amp;ldquo;ctrl + 鼠标左键&amp;rdquo;，而不是&amp;ldquo;ctrl + r&amp;rdquo;，这说明你必须重新审视你对pureMVC框架的理解了，请审查你的Mediator类，看里面是不是充斥着大量的public方法，如果你的对象之间依旧是通过public方法进行引用，而不是通过Notification通讯的，那你也没有必要继续使用pureMVC框架了。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;4，单例模式影响到底有多大？pureMVC是一个完全依赖单例模式的框架。单例模式似乎在AS界一直有很大争议，这样的话，pureMVC肯定也会有相应的争议了。持反对意见的人，大多集中在&amp;ldquo;性能&amp;rdquo;和&amp;ldquo;团队协作&amp;rdquo;方面，他们认为一个单例持有过多引用会带来性能问题，而且生怕在团队协作中自己的单例类被人无意修改，引发离奇的BUG。性能方面，我之前也没做过10W以上的项目，不敢妄言，但10W行以下的项目，绝对没有问题，如果你两三万行的架构就开始碰到主架构性能问题，估计十有八九是自己的代码写的有问题；团队协作方面，我觉得pureMVC的Fa&amp;ccedil;ade模式是非常灵活好用的，大家可以略做讨论，制定一个简单的规则，比如模块只能通过fa&amp;ccedil;ade获取数据和发送Notification，不能直接调用主程序其他CLASS，只要架构程序员不犯错，模块程序员甚至连犯错的机会都没有，如果他们有，还是你的架构思路有问题，请继续审视自己的代码。反正单例模式的问题到底是什么，我到现在也没完全搞懂，主要是我们的项目没碰到过此类问题，希望碰到过的朋友能再仔细跟火山说说，我也好弄清楚问题到底出在哪里了，自己以后可以更好的避免此类问题发生。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;额，框架部分先谈上面4点吧，赶快进入下一个话题，模块划分：模块划分主要包括&amp;ldquo;核心模块划分&amp;rdquo;和&amp;ldquo;子模块划分&amp;rdquo;。核心模块的划分思路是这样的：它们是游戏启动所必须的，相互之间是紧密联系的，还要经常的被子模块调用；而相对的，子模块的划分思路是：他们在游戏启动过程中不是必须的，可以在游戏过程中再加载，子模块相互之间基本上完全没有联系，一个子模块的增加和删除不会影响到任何其他子模块，子模块可能需要调用主程序的接口或者获得主程序的数据，但主程序绝对不应该依赖某个子模块。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;明确了模块划分思路再具体看看哪些部分应该划分为核心模块，哪些部分应该划分为子模块。一般情况下，核心模块按照游戏启动顺序包括：一个壳子SWF &amp;rarr; 配置文件包 &amp;rarr; 登录注册SWF &amp;rarr; 主程序SWF &amp;rarr; 主UI的SWF &amp;rarr; 公共素材包。而子模块相对来说简单很多，比如具体的某个小游戏，某个场景，以及某个场景里的触发功能等等。下面我对核心模块逐一略做解释。&amp;ldquo;一个壳子SWF&amp;rdquo;：这是一个体积很小，但意义很大的SWF；它后面总是跟着随机变量，确保每次用户加载的都是最新的；它里面定义着一些需要经常更新而且每次更新都必须保证用户也在第一时间就得到最新值的变量；它里面最好有一个简单背景图，保证用户在超低网速的时候输入游戏网址不至于长时间面对一片空白；它里面有安全策略的设定，是我们游戏和很多第三方平台合作的基石；它里面还定义着主程序被加载进来之前的游戏启动流程等等。&amp;ldquo;配置文件包&amp;rdquo;：核心模块版本号啊，全局文字说明啊，service接口定义啊，各个核心模块需要的配置信息啊什么的，一般是一些XML文件。&amp;ldquo;登录注册SWF&amp;rdquo;：这个简单，在加载重量级的SWF前，先加载登录注册SWF,可以保证用户第一时间就能打开登录注册界面，而且可以有效节省服务器带宽。&amp;ldquo;主程序SWF&amp;rdquo;：这个就是我前面费了好大劲讲的主程序部分了。&amp;ldquo;主UI&amp;rdquo;：主程序和主UI为什么要分开两个SWF，我前面已经提过了，后面还有说明，这里暂时不讲。&amp;ldquo;公共素材包&amp;rdquo;：公共素材包是一个游戏不可缺少，但也不能过分依赖的东西。它包括一些全局的道具和效果，比如表情、技能特效、场景传送门等等。公共素材包里面最好就是一些简单的动画，体积小功能简单，严禁在公共素材包里添加上百K的东西，或者代码上百行的小模块，公共素材包建议500K以下。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;看了上面的讲解，你可以能觉得核心模块分那么多，太麻烦了。不错，在我看来，对SWF加载流程的分解和控制，对异步程序的掌控正是衡量一个AS程序员是否经验丰富，是否足够老道的重要指标，很多从其它语言转到AS并有多年编程经验的朋友，架构方面可能和AS程序员差不多，甚至比很多自学成才的AS程序员做的更好，但这方面往往不如长期与CPU和SWF体积搏斗的老牌AS程序员。核心模块划分的越合理，用户体验往往越好，后期编写和维护代码的效率会越高，但在前期会比较麻烦，而且对架构师的架构经验和能力必须提出更高的要求。什么都不分，主程序、素材、核心模块都弄在一个SWF里，用户一开始必须先下载完这个SWF,或者弄了一堆核心模块和超多公共素材，用户一开始必须面对loading条不停的周而复始，必须等所有核心要素全部加载完成才能进行一些基本操作的做法，从架构角度上讲，是最简单的做法，因为不用过多考虑复杂的异步和SWF拆分问题，但从用户体验和长远的开发维护上讲是非常不利的。根据我们的经验，用户登录前加载的所有资源体积应该控制在200K左右，而用户进入游戏主场景前，加载的资源总数应该控制在1M左右。还有前面提到过的那位用了pureMVC后项目编译一下要十几分钟的朋友，估计就是把所有东西都弄到一个SWF里的做法。主程序随便改动测试一下，就要十几分钟，牵一发而动全身，开发效率从何谈起？根据我们的经验，任何主程序、核心模块还有子模块的编译，都必须在10秒以内，这才是合理的&amp;mdash;&amp;mdash;我的机器是07年花了3000多买的戴尔品牌机。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;谈完主架构，接着谈主UI。主UI一般指主要的人机交互界面，这里的主UI区分于主架构中的mediator，当你看过pureMVC文档后，你就知道了，mediator只不过起到一个真正的V和pureMVC框架之间的桥梁作用，pureMVC里的mediator其实并不实现什么功能，真正的功能都是在主UI里实现的。但主UI又不得不算是主程序的组成部分，因为它不像其他模块，基本上只需要调用主程序的接口就行了，本身并不需要对主程序提供接口。而主UI作为用户操作界面，必须大量的向主程序的mediator提供接口，或者发送events。所以主程序和主UI之间的配合必须非常密切才行。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;不同的游戏类型，可以选择的UI解决方案也不同。策略类非常适合用FLEX；MMORPG这类标准网游，非常适合用ASWING；而像我们海底世界这类游戏界面非常夸张，没什么标准规则，又不是太复杂的界面，还是适合自己开发。相信任何有过游戏项目经验的人都应该能理解，UI也是FLASH开发中的重头戏，很多细节的处理非常麻烦，在项目早期具有很大的工作量。还是以我们的项目为例，我们的UI架构思路是这样的：&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;1，所有的界面组件都是直接拖放在stage上的，其功能代码大部分都是在发布时编译的，基本上不用new的方式。这种方式的好处是方便编辑界面，从总体上直观的把握所有的UI，减轻程序运行时的负担，同时避免addToStage带来的诸多问题。缺点是，当UI膨胀到一定规模时，可能会需要你有一台配置比较好的电脑&amp;mdash;&amp;mdash;哎，说到这里我就伤心啊，我那台玩魔兽效果全关还卡的电脑，一直陪伴我的整个UI开发历程。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;2，UI的FLA层次结构是这样的：第一层是文档类或者与UI主类关联的某个MC，我们选用的是MC的方式,因为MC的方式更灵活；第二层是这个MC里的所有组件，这些组件大部分是根据功能划分在一起的一组元件，比如你的个人面板，而这个组件本身也是个MC；第三层是组件里的所有元件或者共用组件，元件就是背景啊，按钮啊什么的，而共用组件比如滚动条啊翻页组件啊什么的；主要的就这三层，其实那些共用组件MC再往里面双击还可以划分一层。对应FLA的层次结构，AS的结构如下：文档类或者主MC关联的类是第一层，这个类里持有所有的界面元件的引用；第二层是这些界面元件对应的组件CLASS,组件的功能都是在这里实现的，比如个人面板的MC将会对应一个MyPanel的CLASS,这个CLASS里实现MyPanel的所有功能。至于CLASS和元件之间是怎么对应的，我用的是一种松耦合的代理模式，也就是将MyPanel对应的MC作为参数传递给MyPanel这个CLASS,而这个CLASS会有自己的私有变量记录对应MC里需要进行操作的元件，具体到功能实现时，从代码层面上看，就好像CLASS操作的都是自己的私有变量，而不是直接操作界面元件，这样，当界面元件修改名字时，CLASS的改动很小。而且这种代理模式可以实现一个CLASS代理不同的元件，当界面只是需要修改外观，不需要修改功能时，非常方便。那么这些CLASS是在哪里初始化并获得它要代理的MC呢？正是在主MC对应的UI主类中，比如当获得MyPanel对应的MC后，就会立刻public var myPanel:MyPanel = new MyPanel(myPanel_mc);当所有的组件注册完成后，这个UI主类就持有了所有组件的引用，可以方便主程序调用；代码的第三层其实就是共用组件，比较特殊的是，我的共用组件，比如滚动条，也是用代理模式写的。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;3，完全代理模式为我们创造了一种可能，就是把UI和UI对应的代码分开编译。这跟FLEX的皮肤更换机制有异曲同工之妙，只不过它的组件是要new出来的，布局是要代码控制的，皮肤都是一个个CLASS，整体效果一般都要编译后才能看出来；而我的组件是直接拖到舞台上的，布局大部分是直接在FLASH IDE里手动布置好的，皮肤都是一个个命名过的MC，整体效果编译之前基本上就能看出来。FLEX在更换皮肤的时候，CLASS名绝对不能变，而我的UI在更换皮肤时，MC的名字和层次结构不能变。FLEX关联皮肤是在编译时完成的，而我的UI关联皮肤是在运行时，当启动程序加载完UI代码的SWF和皮肤的SWF后，动态指定的。把皮肤和功能代码分开编译成两个SWF有个好处，就是在实际开发过程中，我们会碰到有时候只需要修改代码，而有时候只需要修改界面的情况，当然，就算你把代码和界面一起编译成一个SWF文件了，也完全可以对应这种情况，无非是编译一次的时间稍微长了一点点。可当你面对这样的情况呢：某次游戏版本更新出现状况，需要你目前功能不变，但画面必须退回到上一个版本。这时候你傻眼了吧？你开始对策划们咆哮：&amp;ldquo;你们能不能想想好再让我们做啊？&amp;rdquo;但你还是不得不重新打开已经做好的UI,把里面最新的界面再修改回老版本，同时还不敢把最新的删了，因为下一个版本估计马上又要替换回最新的画面了。可如果你的皮肤和代码是分开编译成两个SWF的，这种情况就简单了，你可以让运维从SVN上拉出上一个版本的皮肤SWF重新发布一下就好了，你所要做的只不过是动一下嘴皮。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;4，最后谈一下UI的数据层吧，UI是否需要数据层呢？答案是肯定的。尽管你可以从主程序那里获得任何你想要的数据，尽管大部分时间你只是需要数据来显示一下而已，但UI自己记住某些数据会大大方便自己写代码。UI的数据层不需要主程序那么复杂，每个组件有自己的数据变量，然后整个UI再有一个存放公共数据的地方就足够了。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;谈完主程序和主UI，最后再简单谈一下小游戏、场景和模块。先说小游戏吧，小游戏是相对最独立的一块，可能只需要主程序提供用户数据，并在游戏结束后将分数发送给主程序就行了。所以这部分从管理的角度上来讲是相对轻松的，但这不意味着小游戏开发就简单了，有时候，麻雀虽小五脏俱全，想开发出一个性能和用户体验俱佳的小游戏绝非朝夕之功，要是碰到一些算法复杂的小游戏，那就有得头痛了。其实对于海底世界这类儿童社区游戏，小游戏应该走创意和简单路线，搞得太复杂了，既不好开发，小孩子又不一定玩得来。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;相对于小游戏，场景和模块就和主程序甚至是主UI关系密切了，但不管怎么密切，大部分时候它们都是在所要数据，发送事件，或者触发某个界面的显示与隐藏。如果某个模块的修改需要经常波及到主程序，或者很多模块在做同一件事，重复写着同一段代码，这时候就必须重新审视架构，看是不是某些地方架构的不合理了，不合理的地方，只要时机允许，一定要尽快改掉，绝对不能放任自流，一块儿小毒瘤最终可能引发癌症。模块和场景程序员在我们公司其实是非常累的，因为每周都需要发布新的版本，每次都很赶。在这种情况下，场景和模块程序员的责任心就非常重要，他们随便哪里随意了一下，会直接导致糟糕的用户体验，因为大部分时间，用户直接接触的东西都是他们的作品。架构写的再好，最终模块都做的很糟糕，对用户来说没有任何价值！所以，一个老道的，有责任心的，能够快速开发出优良用户体验的AS模块程序员，完全有理由拿高薪，因为他们能做到的，一些所谓的纯架构师未必做得到！&lt;/p&gt;&#xD;
&lt;p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0.9em; margin-left: 0px; line-height: 19px; font-family: 'Microsoft YaHei', Georgia, serif; font-size: 14px; padding: 0px;"&gt;&lt;strong&gt;★前端与美术的配合&lt;/strong&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;老闪客们应该都知道，FLASH这款软件在历史很长一段时间内都是用来做动画的，闪客和美术在这段时间内本就是同根生。后来随着第二版AS1和AS2逐渐完善，以及AS3的强势出炉，闪客们才逐渐分化成纯程序和纯美术两个阵营了。但不管怎么分，FLASH程序和美术之间的关系依旧非常亲密，一个优秀的AS程序员必然要比其它语言的程序员懂得更多美术方面的知识，至少也要能熟练操作FLASH IDE，并进行简单的图形处理。FLASH程序员与美术的合作大部分时间是由AS程序员主导的，主要表现在以下几个方面：&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;1，FLA文件管理：把有联系的美术素材放进一个FLA文件中统一管理，既能有效减少美术素材的数量，也方便程序员写程序。本来像这种美术素材管理应该是由美术负责的，但由于这些美术素材大部分时间可能也需要程序员写程序，美术和程序需要共享这些素材，虽然我们可以用SVN进行共享和版本控制，但程序员和美术还是要靠约定才能非常默契的知道什么时间该到什么地方找什么文件。而这个约定就什么我们程序员应该制定的，因为据我观察，程序员在条理性和制定规则方面一般比美术更靠谱。以我们公司为例，文件管理基本上都是由我负责的，我把需要多个美术和程序员共同维护的部分以项目名命名成一个文件夹，项目下如果需要还可以进行子分类，分类规则也是我制定。而大部分的子模块可能只需要一个美术加一个程序员就搞定了，这时候美术就把素材放到以自己英文名命名的文件夹下，至于他们的文件夹内如何分类，我会给出意见，但并不强制管理。模块程序员也会都有以自己英文名命名的文件夹，他们会把美术的纯FLA素材拷贝到自己的文件夹下，并根据模块进行子分类，然后写代码并发布SWF，至于SWF文件如何管理，我会在下一节中讨论。其实我的管理目标非常简单，我只需要所有的美术和程序员能在任何时候瞬间找到我们需要的素材和源代码所在地，并且把需要的版本调出来。只要这个目标还在可控范围内，我就会给所有员工最大的自由性，把自己从管理里解脱出来，把更多的时间投入开发，毕竟对于创业型公司而言，快速开发，让老板和市场看到产品才是主旋律，管理只需要在必要的时候强势出手就可以了。事实上，我们公司的文件管理，我每隔半年才会强势管理一次，用大概一周的时间重新规范规则，其它时间基本处于放任自流状态，但从没出过什么大问题。最后给大家一个数字，我们公司经过将近三年的积累，已经有几十个G，上万个美术素材了。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;2，SWF文件管理：SWF文件一般是由前端程序员发布并管理的，不过也有一些SWF可能不需要些代码，比如家具、个人面板背景等等，这些可以直接由美术管理，管理方案和FLA文件管理差不多。最大的不同就是，SWF文件最终的发布路径是内网模拟测试环境，而不是本机。像我们这样的更新驱动游戏，不可能为每一个模块都单独搭建拟真测试环境，如果这样的话，可能我们测试环境还没搭好，就该上线并准备下一周的更新了，所以所有的模块最终的整合测试都是直接上内网测试环境进行。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;3，FLA内元件的管理：这个问题相信很多AS程序员都碰到过，也都为此头痛过。美术给到程序员手里的FLA文件可能是混乱不堪，库里没有任何分类，元件名也都是清一色的&amp;ldquo;元件1、元件2，元件3&amp;hellip;&amp;hellip;&amp;rdquo;，元件内部遮罩，组合，层次也都没啥规律。要是美术直接给我一个AI或者PS的源文件让我们自己导入FLASH，那我们就更抽了，颜色模式的改变，路径工具的失灵，大量的图层导致裁切困难，而且还不能进行打散合并，只能一层一层的切。这个时候，正如我前面提到的，一个合格的AS程序员应该对美术和图形软件有更多的了解，你应当及时纠正美术不恰当的做法，甚至给出合理的解决方案，比如你应该知道FLASH只支持RGB颜色模式，AI不但整个文档可以指定颜色模式，每个图层也可以单独指定，当美术给到你的AI导入FLASH有色彩差异的时候，能帮助美术找到哪里的颜色模式不对，并建议他们以后只使用RGB模式。很多纯AS程序员可能有图形恐惧症，他们会想尽一切办法把这部分工作推向美术，但最终他们都会很郁闷，因为他们会发现，除了能指定库文件夹的命名规则外，其它的规则很难跟美术说明白，而且由于模块的千变万化，很难总结出一个完全通用的规则，想从美术哪里拿到一个完全不用修改，自己可以直接写代码的FLA文件，几乎天方夜谭。所以，与其让FLA文件在美术和程序的你来我往中浪费时间，与其让自己在对美术的鄙视中愤懑抱怨，不如提升一下自己的美术常识和图形处理基本功。毕竟，元件在舞台上怎么命名，关联什么类，层次怎么样，怎么被程序利用，这些只有我们程序员最清楚，这部分工作由我们程序员完成完全是合理的，也是效率最高的，美术只要把我们需要的素材交给我们，并放到方便查找的地方就可以了。放下程序员的架子，主动走入美术的世界，对我们程序员绝对有好处。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;4，FP的性能问题对美术的影响：谈到这个问题，我就想起了一个让我抽搐已久的情况。我们老板总是喜欢语重心长的对我说：&amp;ldquo;火山，你给咱们前端人员和美术出一个方案吧，告诉他们怎么做可以让FLASH性能最高！&amp;rdquo;额，现在请问哪位朋友可以帮火山回答这个问题。火山真的惭愧，搞FLASH搞了7年了，始终还是没完全弄明白FLASH的诸多性能问题。不管以前的MM还是现在ADOBE，都将其图形处理和屏幕渲染部分视为其镇山之宝，不肯公开其技术内幕，我也就始终无法从理论的高度给出一个本质的回答。我现在的大多数性能解决方案，都是根据项目的实际情况，根据7年来的经验总结出的经验科学。而且我始终不相信，谁可以一个给出一个适合所有项目的、通用的性能解决方案，可以同时让内存、CPU、带宽占用都最少，而且画面又很炫，功能很强大，SWF文件非常小，可玩性非常高，而开发周期和成本却很少。内存、CPU、SWF体积、带宽、效果、成本，这几个要素往往是相互矛盾的，你对其中任何一点的过分优化，都有可能导致其它点走向反面。我深信，在目前这个时期，一个性能方面的高手，绝对不是看他能不能给出一个全面优化的方案，而是看他在面对不同的项目，不同的情况时，如何做出选择和取舍。是的，&amp;ldquo;选择和取舍&amp;rdquo;永远都是人生最艰难的话题：手心手背都是肉，削掉哪边呢？老婆孩子都掉海里了，救谁呢？在这样的情况下，我觉得一个负责的前端人员，反而不应该仅仅简单的扔给美术一份死的文档，告诉他们应该怎么做，让他们一直这么做就可以了。前端人员应该在每次面对一个实际情况时，都不厌其烦的跟美术讲清缘由，我们应该尽量授人以&amp;ldquo;渔&amp;rdquo;，而不授人以&amp;ldquo;鱼&amp;rdquo;，让他们明白选择的道理，而不是简单的告诉他们选择什么。相信只要是虚心学习的美术，经过一年半载的讲解他们就能替你做出判断了，这时候你再让他们去跟后来的美术讲，你就解脱了。很可惜，大部分不懂技术的老板可能觉得你是在故弄玄虚，非要你给出一份文档。无所谓了，你跟不懂技术的人争论不是自讨没趣么？老板更多时候是从管理的角度出发的，我们应该配合。我们也不是没什么可写，比如尽量减少元件数量啊，减小SWF体积啊，减少持续性动画啊，多做触发性动画啊，少用遮罩和滤镜啊，不要嵌入中文字体啊，提高元件重用性啊等等等等！这些建议听上去完全正确，忽悠不懂技术的人正合适。但其实在高端的开发中，这些理论都是废话，帮不上多大忙，因为地球人都知道了，我们碰到的问题肯定是超越这些技术点的高端问题！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;综上可以看出，其实前端和美术的配合过程大部分时间是由前端主导的，这也是我前面一再强调前端要多懂一些美术知识的重要原因。当你可以和美术一起谈论美术理论，在美术的电脑上直接操作给他们看，当你从美术的角度给他们提出解决方案的时候，你往往会更容易被美术所接受。担负起主导前端与美术合作的责任，用你的智慧征服他们，用你的诚意打动他们，让美术与前端完美结合，让你的产品第一时间抓住用户！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;strong&gt;★前端与后端的配合&lt;/strong&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;FLASH与后端通讯的手段多种多样，网上相关教程太多了，这里不再例举。但很多时候，创业团队由于受制于各种现实条件，可选择的方案并不多。像我们公司，刚开始基本上只能选择FMS+PHP+MYSQL。其实，对于我们前端来说，后端选择什么解决方案对我们的影响并不大，我们无非就是用的API不一样而已。多看看教程，用很少的时间我们就能掌握其要领。那么前后端合作的难点是什么呢？我觉得关键是逻辑的划分。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;&amp;ldquo;前后端合理划分逻辑&amp;rdquo;，这句话咋看上去貌似简单，其实里面蕴含着诸多方面的考虑。比如安全性、后端性能、工作量、人事分工等等。安全性：记得我们的游戏同时在线超过3000的时候，就已经有人开始攻击我们的后端了，篡改了很多人的个人资料。幸亏攻击的人只是我们一个善意的玩家，如果是恶意的商业攻击，后果不堪设想。经过这次后，老板开始缠着我们追问&amp;ldquo;怎么防止别人攻击，提高安全性&amp;rdquo;。这个问题又一次把我们难住了，我们都知道，基于HTTP的请求不被截取是不可能的，而SWF文件又不存在绝对的安全。就算你防得了恶意进攻，你也防不了良性的外挂，想从技术层面让别人完全攻击不了我们也是不可能的。那我们是不是只能坐以待毙了？不是！如果前、后端在合作的时候，数据逻辑与合法性检查都是做在后端的，就可以很好的避免一些良性外挂。首先是游戏数据逻辑要尽量全做在后端，比如用户在玩小游戏的时候，我们不要只是在用户结束小游戏后，简单的把数据传回后端，后端记录进数据库完事，一旦攻击者发现了你这个传数据的后台接口，完全可以避开SWF，做外挂直接呼叫你这个接口刷分，就算你验证用户也没用，因为他可以先注册一个合法的用户，然后在外挂中登录再刷分。当然，你还可以对游戏分数先加密在传给后端，提高攻击难度，但这也是不保险的，因为加密算法就在你的SWF文件中，别人可以很容易获得。所以正确的做法应该是：游戏开始的时候只告知后端游戏ID&amp;rarr;后端标识ID对应的游戏已经开始并记录开始时间&amp;rarr;用户每次获得一个分数时，前端传回来的不是分数，而是一个动作ID,后端根据动作ID给用户加分&amp;rarr;游戏结束时，前端告知后端游戏已经结束&amp;rarr;后端得知游戏结束，记录结束时间，计算时间差，根据时间差和最后得分是否符合标准做出相应处理，如果符合标准就把最后得分入库，并返回前端显示给用户，如果不符合标准，就启动作弊处理系统。而这个标准一般是由数值策划给出的。经过我这么一分析，你可能头痛了，本来一个很简单的小游戏计分，怎么搞得这么复杂？前后端工作量都增加了不说，对后端性能也提出了更高的要求，服务器可能要增加了，后端人手可能要增加了，开发周期也要延长了，值得么？这个问题问的很好，这正是我下面要说的：后端性能、工作量、人事分工：一旦我们每一步进行安全性与合法性验证后，整个项目的工作量都会大大膨胀，开发周期也会大大延长；一旦我们把数据处理、业务逻辑和安全验证都移到后端时，后端的压力就会增加，服务器要增多，对后端人员的能力要求也会提高。很多初创团队在项目初期人力财力，软件硬件都不足，可能顾不上那么多，一心想着早点让项目上线。在这种情况下，我觉得安全性可以暂时放一下，众所周知的安全漏洞补上就可以了。但&amp;ldquo;数据处理和业务逻辑&amp;rdquo;这个，宁可开发的慢一点，宁可再招个后端高手，宁可多几台服务器成本，也要把它们尽量都放在后端。因为这个没分清的话，会影响到整个系统的清晰度，严重影响项目中后期的发展，为日后的重构增加难度和超多的工作量，我们还指望着在重构时加强安全性呢，到时候数据处理和业务逻辑还是要放后端！所以综合考虑，该出手时就出手，能省的不浪费，不能省的不要抠！&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;前面一节谈了前后端合作的难点。这里再简单的谈两个要点：&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;1，前端人员不要以前端的角度看后端：前端和后端有个本质的区别，就是前端的负荷是分担在每个客户端的，而服务端的负荷是集中在服务器上的。对于我们前端来说，一个功能多占了几K内存，SWF文件大了几K根本不是什么问题，可对后端来说就是很严重的问题了，一个人大几K，上千人就是几M了。服务器在连接数、内存和CPU之间会有微妙的平衡点，一旦这个平衡点被打破，随便再多哪怕一点点资源占用，整个服务器的性能都会严重下降，影响用户体验，当然，如果你有几十上百台冗余服务器供你负载平衡，你可以当我没说，可如果你像我们公司一样，一开始就3、5台服务器的话，就请前端人员一定要多多配合后端人员，帮他们省出每一个字节，每一次请求。比如像道具属性会有很多文字说明，这些说明应该以类似XML文件的方式储存为静态文件，后端返回给前端的道具数据包里只需要一串物品ID,前端就可以根据这些物品ID在XML文件里查询出这些道具对应的静态物品属性了。别看这些数据可能只有十几K，对后端来说意义重大。还是那句话，只要不是架构性问题，前端不要怕麻烦，要尽量配合后端提高性能。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;2，前端后端要有很明显的BUG分界点。当一个BUG出现时，后端应当很快的用一种统一的方案证明数据没有问题！这个方案必须让前端知道，并让前端也可以操作。大家熟知的php remoting里有一个servicebrowser，这个东西就很好，它能罗列出所有PHP的接口，我们输入参数，它就返回结果，我们可以根据结果直接查看数据是否正确。&amp;mdash;&amp;mdash;确定数据的正确性，对前端DEBUG非常重要，而一个BUG的解决，一般都是由前端人员入手并进行定位的。&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&lt;br style="word-wrap: break-word; line-height: normal;" /&gt;&amp;rarr;其实相对于前端和美术的合作，前端与后端的合作还是简单清晰的，前后端在开发的过程中，应该是非常独立的，后端开发完全可以先启动，把数据接口提前写好，等着与前端整合，而当整合过程发生问题时，又可以很快的界定是谁的问题。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/sun11086/aggbug/1674036.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/sun11086/archive/2010/02/26/1674036.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
