About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • May

    27

    词法作用域就是指定义代码的时就决定了作用域范围,解释一个术语时最好的方法就是举一个简单的例子,下面这段虽然的  JS 代码,但它适用于所有包含词法作用域语言的概念:

    <script>
    var str = "global";
    function test(){
        alert(str);
        var str = "local";
        alert(str);
    }
    test();
    </script>

    如果不了解词法作用域,可能会认为上面的代码会先输出 global,然后再输出 local;事实际上它是先输出 undefined,然后再输出  local。

    JS 通常情况下定义一个函数后,它就是词法作用域,这意味着它运行在自己定义的作用域中,而不是运行在执行代码的作用域中。JS 解析器在加载 JS代码后并不会立刻执行,而是先解析 JS 代码,上面的函数实际上会被编译成如下类似的代码,然后再运行编译后的代码:

    <script>
    var str = "global";
    function test(){
        var str;
        alert(str);
        str  = "local";
        alert(str);
    }
    test();
    </script>

    但类似 JS 这样的语言本身也有例外情况,比如函数本身可以通过构造函数来动态的创建,并且 JS 解析器可以读取动态创建的 JS代码,并编译它们然后运行,但此时动态创建的函数并不使用词法作用域,编译后的代码当作顶级函数来编译。

    <script>
    var str = "global";
    function test(){
        var str = "local";
        return new Function("return str")
    }
    alert(test()());
    </script>

    所以上面的代码运行结果输出 global。但这种情况并不适用于所有需要预编译或需要编译后执行的代码,比如类似 Flash AS 这样需要预编译的代码,因为所有 Adobe 官方的 Flash 运行时环境都只有加载 ABC 码和解码的功能,运行时环境本身没有编译 ABC 码的功能。

    May

    25

    <script>
    var f = function fact(x){
        if(<=1)
            return 1;
        else 
            return x * fact(x-1);    
    }
    alert(f(2));
    alert(fact(2));
    </script>

    这是一个看起来像是有命名的函数直接量。为什么说它看起来像是有命名呢?因为要分情况。

    在 IE 8 中测试结果发现它真的就像命名函数一样,甚至可以将 alert(fact(2)); 提前到函数直接量表达式的前面;

    但在 Google Chrome 35 中上面的代码最后一行会产生一个运行时错误(因为访问了一个不存在的定义)。如果将上面代码中的最后两种交换位置,在 Chrome 35 中不会输出任何内容,因为当 alert(fact(2)); 运行产生错误时会静默失败,然后后续代码会全部中止运行。

    而事实上这种看起来好像有命名的函数直接量只允许 JS 1.5 后的版本中使用,并且是只允许的在函数体内用这个名字来引用自身(比如类似上面的嵌套函数)。

    所以,如果不是想要展现自己在特定平台开发的编程技巧,就算有脚本标准,最好也不要使用奇葩的写法(因为不同浏览器厂商未必都遵循标准),除非那个脚本语言是被垄断性的只能运行在特定的平台,比如 ActionScript。

    May

    25

    使用 with 语句虽然能使用代码变简洁,减少代码的输入量,但它并不被开发者们推荐(甚至在 ECMAScript 5 的严格模式中遭到了禁用)。因为在使用 with 语句时,代码的运行速度会比不使用时更慢。并且在 with 语句内定义的变量作用域情况比较复杂,也会让初学者迷惑。看以下样例代码:

    <script>
    function fun(){
        var x = 9;
        var y = 10
        with(Math){
            var larger = max(x,y);//显示声明,这个变量是定义在函数内的,作用域是在函数层级,与x、y相同。
        }
        alert(larger);//10
        alert(Math.larger);//undefined;虽然在with内声明,但并不属于with的目标对象。
    }
    fun();
    alert(larger);//访问不存在的变量,这里就会产生一个异常,因为在函数外没有定义。
    </script>

    然后再试一下隐式声明:

    <script>
    function fun(){
        var x = 9;
        var y = 10
        with(Math){
            larger = max(x,y);//隐式声明一个变量时它的作用域是全局的
        }
        alert(larger);//10
        alert(Math.larger);//undefined;
    }
    fun();
    alert(larger);//10,访问全局的变量。
    </script>

    备注:由于 AS 与 JS 遵循相同的 ECMA-262 标准,尤其是熟悉和精通 AS1、AS1.1、AS2 的人可能会对这种 JS 的作用域更熟悉(AS1.1 与 JS 之间完全可以轻松的共享代码)。

    May

    25

    JS 运行时环境(JS 解析器)需要先加载 JS 代码时,然后解析(编译)JS 成为可执行代码,然后运行可执行语句。而函数定义实际上是在解析时发生(也就是在运行 JS 代码之前)。

    <script language="javascript"> 
    alert(f(4));
    var f = 0;
    function f(x){
     return x * x;
    }
    alert(f);
    </script>

    先输出 16,再输出 0。这种解析过程往往被称为“函数向前引用”,就好像函数定义被提前到了所有可执行语句之前。实际函数定义在加载 JS 并解析时就动态生成了一个与函数名相同的变量名,所以当后面相同的变量名再次出现时覆盖了前面变量的定义(函数定义和变量定义并不在同时发生)。

    May

    25

    在 Flash IDE CS3 以上版本中输入以下代码,并编译:

    undefined=1;
    null = 1;
    NaN = 1;
    2 = 1;

    在编译器的报错对话框中可以看到如下三行说明:

    1049: 对指定为常数的变量进行的赋值非法。
    1050: 无法为非引用值赋值。
    1049: 对指定为常数的变量进行的赋值非法。
    1050: 无法为非引用值赋值。

    undefined 并不是一个真实的对象,而是一个全局的常量名,它所引用的对象表示未定义的对象;而 null 是一个真实的值对象(字面量直接表达式,就像上面的 2 就表示值是 2 一样),就表示为“空”值。事实上通过以上代码也可以看到 NaN 也是一个常量名,它引用的对象表示非数字,并不是一个真实的值对象。

    实际使用中的区别查看《AS3 中 null 与 undefined 的区别》。

    May

    24

    JavaScript 本身并不令人讨厌,比如在一个独立的客户端程序中嵌入特定版本的 JS 解析器,就会非常方便。

    但它却被 Web 开发者们厌恶的最大理由就是需要到处调试,因为不同的浏览器解析出来的结果往往不同,下面用一行代码示例说明 JavaScript 是一种值得唾弃的语言。随意创建一个 *.html 文件,并输入如下一行代码。

    <a href="javascript:5%2">A</a>

    用 IE 8 打开后测试,返回一个字符串作为新文档显示结果 1,并且浏览器的返回按扭变成可用,基本上可以认为它的解析过程与我们相要的效果相当(以 《JavaScript 权威指南》一书中介绍的为标准);但当使用 Google Chrome 35 版本作为浏览器测试时,发现点击没有任何效果。

    对它稍作修改如下:

    <a href="javascript:(5%2)+''">A</a>

    IE 8 与 Chrome 35 都返回新页面显示结果 1,这说明 Chrome 对基本数据类型有自动转型的功能,但在第一次的代码中它并没有自动转型。其中与 IE 8 仍然有细节上的差异,IE 8 在显示结果 1 时,产生新的历史记录页面,浏览器的返回按扭变成可用,但 Chrome 返回按扭仍然不可用。

    这如何让前端开发者们不唾弃这种语言,尤其是 Web 前端开发者,每写一个功能甚至一行代码,就需要从一种浏览器调试到另一种浏览器,测试功能与效果是否能实现需求相同(这里例举的仅仅只是两款主流的浏览器其中的一个版本)。

    More...

    May

    23

    Adobe Scout 相关资料

    • 0 Comments
    • Flash Platform

    May

    23

    个人房屋租赁合同范本下载

    • 0 Comments
    • Miscellaneous

    范本下载:租房合同.rar        样本预览:租房合同.pdf

    May

    22

    包含主要内容:关于 FXG 介绍、使用 FXG 的最佳实践、以 FXG 格式存储 Illustrator 文件、Illustrator 和 Flash Catalyst 工作流程、Illustrator 对象和属性的 FXG 映射。

    链接地址:http://help.adobe.com/zh_CN/illustrator/cs/using/WS3f28b00cc50711d9814a4f8133b3babd90-8000.html

    May

    21

    AS3 排序算法

    • 0 Comments
    • Flash Platform

    AS3 的 Array 类型有内置的原生 sort(...args) 方法可以用来排序(args 参数可以用来控制不同类型的元素排序,可以同时传多个参数)。但假设没有这个原生方法,比如从其它某些语言转到 AS 开发的人员,不知道有这么一个方法,想要自定义排序算法:

    //冒泡排序
    function f1(arr:Array):Array
    {
        for (var i:int = 0; i < arr.length; i++)
        {
            for (var j:int = i+1; j < arr.length; j++)
            {
                if (arr[i] < arr[j])
                {
                    var m:int = arr[i];
                    arr[i] = arr[j];
                    arr[j] = m;
                }
            }
        }
        return arr;
    }
    //优化冒泡排序
    function f1_1(arr:Array):Array
    {
        for (var i:int=arr.length-1; i>1; i--)
        {
            for (var j:int=0; j<i; j++)
            {
                if (arr[j] < arr[+ 1])
                {
                    var c:int = arr[j];
                    arr[j] = arr[+ 1];
                    arr[+ 1] = c;
                }
            }
        }
        return arr;
    }
    //选择排序
    function f2(arr:Array):Array
    {
        for (var i:int = 0; i < arr.length; i++)
        {
            var p:int = i;
            for (var j:int = i + 1; j < arr.length; j++)
            {
                if (arr[p] < arr[j])
                {
                    p = j;
                }
            }
            var m:int = arr[i];
            arr[i] = arr[p];
            arr[p] = m;
        }
        return arr;
    }

     三种方法中,冒泡排序速度最慢,选择排序居中,优化冒泡排序算法最快。当然使用 sort()  原生方法是最最快的,所以如果能使用原生方法就尽量使用原生的方法吧。