关闭

10招打通你的js任督二脉

标签: 控制台javascript
261人阅读 评论(0) 收藏 举报
分类:

这段时间一直在看 亚里士朱德的文章,有一篇是我感触颇多,我跟着演示了几遍,也顺便 炒一下冷饭 ^_^

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>十招打通js任督二脉</title>
</head>
<body>
    打开控制台,咱们直接上代码。
    <script type="text/javascript">

        /*第一招:简单回调*/
        //this指针指向当前函数对象
        var simpleCallBack=(function(){
            console.log('这是第一招:');
            this.a="I'm an a";
            function foo(){
                console.log(this.a);
            }
            function doFoo(fn){
                fn();
            }
            function doFoo2(o){
                o.foo();
            }
            this.obj={
                a:2,
                foo:foo
            };
            doFoo(obj.foo);
            doFoo2(obj);
        })();

        /*第二招:用apply改变函数作用域*/
        //apply,call,bind都有个作用就是改变作用域,这里的apply将foo函数的作用域指向obj对象,同时传入参数。
        //再简单分析一下bind函数内部的嵌套,执行bind函数的时候返回的是一个匿名函数,所以执行bar(3)的时候实际上是执行的bind内部的匿名函数,返回的是之前传入的foo函数的执行结果。
        //函数没有返回值的情况下默认返回undefined。
        var applyChangeScope=(function(){
            console.log('这是第二招:');
            function foo(something) {
                console.log(this.a,something);
            }
            function bind(fn,obj){
                return function(){
                    return fn.apply(obj,arguments);
                }
            }
            this.obj={
                a:2
            }
            this.bar=bind(foo,obj);
            this.b=bar(3);
            console.log(b);
        })();

        /*第三招:new关键字*/
        //bind函数的一个参数为null代表作用域不变,后面的不定参数将会和函数本身的参数按次序绑定,绑定之后执行函数只能从未绑定的参数开始传值。
        var theKeywordNew=(function(){
            console.log('这是第三招:');
            function foo(a,b){
                this.val=a+b;
            }
            this.bar=foo.bind(null,'p1');
            this.baz=new bar('p2');
            console.log(baz.val);
        })();

        /*第四招:自执行函数*/
        //立即执行匿名函数可以避免污染全局空间,但很少有人去关注赋值语句执行之后会返回什么结果,其实就是返回当前值。
        //也就是说当括号内执行完成赋值之后,返回的是o对象中的foo函数,函数的执行环境中有一个a对象。
        var executeFunction=(function(){
            console.log('这是第四招:');
            function foo(){
                console.log(this.a);
            }
            this.a=2;
            this.o={a:3,foo:foo};
            this.p={a:4};
            (p.foo=o.foo)();
        })();

        /*第五招:变量属性*/
        //当一个变量被声明之后,扩充其属性并不会改变原数据类型
        var variableAttribute=(function(){
            console.log('这是第五招:');
            this.a=[];
            a[0]=1;
            a['foobar']=2;
            console.log(a.length);
            console.log(a.foobar);
        });

        /*第六招:精度问题*/
        //当操作小数时请小心,js的小数计算并不精确,所以下面的判断是false
        //字符串变量是常亮
        var accuracyProblem=(function(){
            console.log('这是第六招:');
            this.a='foo';
            a[1]='o';
            console.log(0.1+0.2==0.3||a);
        })();

        /*第七招:命名提升*/
        //声明的变量和命名函数都会被提升到代码的最前面,只不过声明的额变量的赋值语句在代码的位置不变。所以下面的代码可以理解为:
        //var foo;
        //function foo(){
        //  console.log(1);
        //}
        //foo();
        //foo=0;
        //foo=function(){
        //  console.log(2);
        //};
        var naming1=(function(){
            console.log('这是第七招:');
            foo();
            this.foo=0;
            function foo(){
                console.log(1);
            }
            this.foo=function(){
                console.log(2);
            };
        })();
        /*更诡异的变招*/
        var naming2=(function(){
            console.log('下面的这招能看懂就是理解第七招精髓了:');
            foo();
            this.foo=0;
            function foo(){
                console.log(1);
            }
            /*下面就开始报错了(可以去掉注释看看)
            this.foo();
            this.foo=function(){
                console.log(2);
            };
            this.foo();
            */
        })();

        /*第八招:作用域*/
        //javascript没有代码作用域,只有函数作用域
        // 下面的代码可以理解为:
        // function foo(){
        //  console.log('a');
        // }
        // function foo(){
        //  console.log('b');
        // }
        // foo();
        // var a=true;
        // if(a){}else{}
        var scope=(function(){
            console.log('这是第八招:')
            foo();
            this.a=true;
            if(this.a){
                function foo(){
                    console.log('a');
                }
            }else{
                function foo(){
                    console.log('b');
                }
            }
        })();

        /*第九招:闭包陷阱*/
        //闭包有个重要的作用就是,在内层函数引用外层函数定义的变量时,外层函数的变量不会被持久化。这里有个隐藏陷阱就是for循环结束之后i仍然自增了1
        var closureTrap=(function(){
            console.log('这是第九招:');
            for(var i=1;i<=5;i++){
                setTimeout(function(){
                    console.log(i);
                },i*1000);
            }
        })();

        /*第十招:伪闭包*/
        // 闭包是函数的嵌套定义,而不是函数的嵌套调用
        var pseudoClosure1=(function(){
            console.log('这是第十招:');
            function foo(){
                console.log(a);
            }
            function bar(){
                var a=3;
                foo();
            }
            this.a=2;
            bar();
        })();
        //那么问题来了,怎么输出3呢?
        var pseudoClosure1=(function(){
            console.log('第十招变招:');
            function bar(){
                function foo(){
                    console.log(a);
                }
                var a=3;
                foo();
            }
            this.a=2;
            bar();
        })();

        /* 
         * @参考:亚里士朱德《十段代码打通js学习的任督二脉》
         * http://yalishizhude.github.io/2015/10/25/10/
         */

    </script>
</body>
</html>

感兴趣的同学可以download下来 演示一下。
原文@ 亚里士朱德《十段代码打通js学习的任督二脉》
http://yalishizhude.github.io/2015/10/25/10/

2
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:203845次
    • 积分:2946
    • 等级:
    • 排名:第12022名
    • 原创:91篇
    • 转载:13篇
    • 译文:2篇
    • 评论:45条
    文章分类
    最新评论