菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
94
0

js 函数

原创
05/13 14:22
阅读数 34450

一、函数的定义

window.onload=function(){
        //函数的调用
        fcName();
        fc1();
        var num=fc2(10,20);
        fc3();
        fc4();
    }
    //函数的参数列表 相当于函数入口;return 相当于函数出口
    /*1.function 语句式
      特点:a.创建一次存储在内存中,每次使用从内存中取,效率高
            b.js 解析器会优先解析然后存储在内存中,使用时直接取内存中的(优先解析)
            c.具有函数作用域
    */
    function fcName(){
       alert("function 语句式");
    }
    /*2、函数的直接量式(ECMAScript推荐)
      特点:a.创建一次存储在内存中,每次使用从内存中取,效率高
            b.js 解析器 只是声明了变量fc1 并没有给其赋值 ,只用当程序运行到这里时才会赋值(顺序解析)
            c.具有函数作用域
    */
    var fc1=function(){
        alert("函数的直接量式");
    } 
    /*
      3.Function 构造函数式
      特点:a.每次创建使用后就会销毁 不占用内存但每次使用都要创建 所以效率低
            b.js 解析器 只是声明了变量fc2 并没有给其赋值 ,只用当程序运行到这里时才会赋值(顺序解析)
            c.顶级作用域
    */
    var fc2=new Function("a","b","return a+b;");
    var fc3=new Function("alert('构造函数式')");
    //三种函数的作用域
    var m=0;
    function fc4(){
        var m=1;
        function fc5(){
            alert(m);// 1
        };
        var fc6=function(){
            alert(m);// 1
        }
       var fc3=new Function("return m;");
       fc5();
       fc6();
       alert(fc3());// 0
    }

二、函数的参数

<script type="text/javascript">
    window.onload=function(){
        fc1(10,20);
    }
    /*
      在js中形参个数可以与实参个数不同
    */
    function fc1(a,b,c){
        var length=fc1.length;//获得形参个数 (不建议使用)
        /*
         arguments 的对象可以访问函数的实际参数(只能在函数内部使用)
        */
        var length2=arguments.callee.length;//获得形参个数(arguments.callee 指向函数本身)
        var args=arguments.length;//实际参数的个数
        var arg1=arguments[0];//获得第一个实际参数
        //在实际开发中我们会先判断参数个数是否相同再执行代码
        if(arguments.callee.length===arguments.length){
           return a+b+c;
        }else{
            return '参数不正确';
        }
    }
    </script>

三、this 关键字

    window.onload=function(){
        //this 对象是指在运行时基于执行环境所绑定的;this总是指向调用者
    }
    var k=10;
    function test(){
        this.k=20;
    }
    alert(k);// 结果为10;
    test();// 相当于window.test();
    alert(k); // 结果为 20  因为 调用 test()函数的是window对象 所以this指向window对象 this.k 覆盖了 var k;

四、call、apply关键字

window.onload=function(){
        // call 、apply 作用一:用于绑定一些函数 用于传递参数、调用
        alert(call1(10,20));//30
        alert(apply1(20,30));// 50
    }
    function sum(x,y){
        return x+y;
    }
    /*
      把 sum函数绑定到this(call1()函数)上
    */
    function call1(x1,y1){
        return sum.call(this,x1,y1);
    }
    function apply1(x2,y2){
        return sum.apply(this,[x2,y2]);
    }
window.onload=function(){
        // call 、apply 作用二:用于扩充作用域
        window.color="red";
        var obj={color:"blue"};
        alert(showColor.call(this));//red 因为this指代调用者window 所以showColor 被绑定在window上
        alert(showColor.call(obj));// blue showColor 被绑定在obj上
    }
    function showColor(){
        return this.color;
    }
window.onload=function(){
        // 模拟 call 、apply 方法的实现方式
        var obj=new Obj(10,30);
        obj.method=test;
        alert(obj.method(obj.x,obj.y));
        delete obj.method;//使用后及时删除 临时调用
    }
    function test(a,b){
        return a*b;
    }
    //自定义的对象
    function Obj(x,y){
        this.x=x;
        this.y=y;
        return x*y;
    }

五、执行环境、作用域链

    执行环境:      在javascript里面执行环境分为两类,一类是全局环境,一类是局部环境,整个页面里被共享的方法和属性就是在全局环境,

                     相对于全局环境,函数{}号里的执行环境就是局部环境,执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为,

                     每个执行环境都定义了一个与之相关的变量对象,环境中定义的所有变量和函数都保存在这个对象里,虽然我们自己编写的代码无法访问这个对象,

                    但解析器在处理数据时候后台会使用到它。
                           全局执行环境另一种说法是最外围的一个执行环境,在web浏览器的范围中(actionscript也是施行了ECMAScript标准,

                    它的全局范围就和javascript的全局范围不同),全局执行环境被认为是window对象,因此全局变量和函数都是作为window对象的方法和属性来创建的,

                   全局执行环境知道应用程序退出比如关闭网页或浏览器才会被销毁。而局部环境则是以函数对象作为关联对象。

作用域链:    Javascript高级程序设计(第三版)(P73):当代码在一个环境中执行时,会创建变量对象的的一个作用域链(scope chain)。

                   作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象

                    。如果这个环境是一个函数,则将其活动对象作为变量对象。

                   每一个函数都有自己的执行环境,当执行流进一个函数时,函数环境就会被推入一个环境栈中,而在函数执行之后,栈将其环境弹出,

                   把控制权返回给之前的执行环境,这个栈也就是作用域链。

自我理解作用域链是由于js的变量都是对象的属性,而该对象可能又是其它对象的属性,而所有的对象都是window对象的属性,

               所以这些对象的关系可以看作是一条链

 

 //1、最外层执行环境 window对象
     var color1="blue";
     function changeColor(){//每个函数 都是一个执行环境
         var color2="red";
         function swapColor(){//该函数 也会产生一个执行环境(variable obj)
             //该函数内部可以访问 color1 ,color2 
             var color3=color2;
             color2=color1;
             color1=color3;
         }
         //这里可以访问color1、color2 但无法访问 color3
         swapColor();
     }
     //这里只能访问 color1
     changeColor();
     //环境变量 可以一层一层的向上进行追溯 可以访问它的上级环境变量和函数

 

六、垃圾收集、块级作用域

 //垃圾回收机制 一.标记法 
      function test1(){
              var a=10;
              var b=20;
      }
      /*
        当执行test()函数时变量a、b 会被标记为被使用,一段时间间隔后会标记为未使用
        这是js的垃圾回收机制会回收a、b
      */
      test();
     //垃圾回收机制二:计数法
     function test2(){
         var a=10;// 被计数 count++  count=1;
         var c;
         c=a; //count++  count=2;
         a=50;// count-- count=1;
     }
     //当count=0 时js的垃圾回收机制就会回收 该变量

块级作用域

/*
        在高级程序预言中 for if 语句具备块级作用域的概念
        在js中没有块级作用域的概念 所以会打印 6
    */
        function test1(){
            for(var i=0;i<5;i++){
                alert(i);
            }
            alert(i);// 6
        }
      // 模拟js的块级作用域 使用()
          function test2(){
            (function (){
                for(var i=0;i<5;i++){
                alert(i);
            }
            })();    
            alert(i);// 这样 i在 for循环结束后 就会被 回收 所以程序出错
        }

七、closure 闭包

<script type="text/javascript">
        var name="AA";
        var obj={
            name:"BB",
            getName:function(){
                return function(){
                    return this.name;
                }
            }
        };
        var fg=obj.getName()();//AA
        //拆开写
        var m=obj.getName();//getName()函数 返回的是一个匿名函数 我们定义我为函数m()
        /*
            很显然m()属于window对象 根据作用域链的特点变量只能向上层层追溯
             所以 this.name指向的是window.name, 因此最终打印AA
        */
        var ff=m();//AA

        //如果我希望最终的结果是 BB 该如何改造代码
        var obj1={
            name:"BB",
            getName:function(){
                var o=this;//this 指向obj1 
                return function(){
                    return o.name;
                }
            }
        };
        var m1=obj1.getName();
        var dd=m1();//虽然m1()函数属于window对象但 它内部的name属性属于obj1对象 所以结果是BB

     /*
        闭包:一个函数可以访问另外一个函数作用域中的变量
        封闭性:起到保护变量的作用
     */
     function f(x){
         var temp=x;
         return function(x){
             temp+=x;//temp又被使用 所以在2级作用域后没有被回收
             return temp;
         }
     }
     var te1=f(20);
     var te=te1(2);//22
         te=te1(3);//25
         te=te1(5);//30
    </script>

 

发表评论

0/200
94 点赞
0 评论
收藏
为你推荐 换一批