zoukankan      html  css  js  c++  java
  • js函数

    1.函数简介

      -Function类型,即函数的类型

      -一个典型的JavaScript函数定义如下:

        function 函数名称(参数表) {

          函数执行部分;

        }

        注意函数的参数表直接写形参名,不用写var类型。

      -return语句,return返回函数的返回值并结束函数运行

      -函数也可以看做数据来进行传递

    <script type="text/javascript" charset="UTF-8">
                
            
                function test(a, b) {
                    
                    return a + b;
                }
                alert(test(10, 20));
                
                // 函数也是一种数据类型
                alert(typeOf test);    // 返回值为function          // 函数可以传递
                function test1(func) {
                    func();
                }
                
                function test2() {
                    alert('aaa');
                }
                
                test1(test2);
                
                // 函数可以嵌套
                function test4() {
                    function test5() {
                        alert('inner');
                    }
                    //只能在函数内部调用,外部不可调用
                    test5();
                }
                
                test4();
            </script>

    2.函数的三种定义方式

    -三种定义方式
       - function语句式

       -函数直接量式

       -通过Function构造函数形式定义函数

    -比较三种方式定义的区别

           
           
           
           
           
           
           

             function语句      function构造函数      函数直接量

      兼容     完全          js1.1以上         js1.2以上

      形式     句子          表达式          表达式

      名称     有名          匿名           匿名

      性质     静态          静态           静态

      解析时机   优先解析        顺序解析         顺序解析

      作用域    具有函数作用域       顶级函数(顶级作用域)     具有函数作用域

    <script type="text/javascript" charset="utf-8" defer="defer" src="../commons/001.js">
                // 3种方式定义函数
                // 1 function语句函数式
                function test1() {
                    // 只会被编译一次,放到内存里,静态,效率高
                    alert('我是test1');
                }
                // 2.函数的直接量式   ECMAScript推荐使用
                // 只会被编译一次,放到内存里,静态,效率高
                var test2 = function() {
                    alert('我是test2');
                };
                // 3.function 构造函数式  
                // 每次都会被编译,效率低,但不占用内存
                var test3 = new Function("a", "b", "return a+ b;");
                alert(test3(10,20));
                
                
                function test1() {
                    alert('111');
                }
                test1();
                
                var test2 = function() {
                    alert('222');
                };
                test2();
                // 执行结果为111 -》222 没问题
                
                // 但是如果将test1和test2分别放到函数体之前执行呢,
                test3();
                function test3() {
                    alert('333');
                }
                test3();
                
                alert(test4); //返回undifind,表示变量声明了,但是没有赋值
                test4();
                var test4 = function() {
                    alert('444');
                };
                // 执行结果为333 ,为什么444没有被弹出,因为只有function语句函数式才是优先解析,剩下是顺序解析
                
                
                // 作用域问题
                var k = 1;
                function t1() {
                    var k = 2;
                    function test() {return k;}    // 2
                    var test = function(){return k;};// 2
                    var test = new Function("return k;"); // 1  原因是具有顶级作用域,相当于在外面(全局)new 了一个函数,所以结果为1
                    alert(test());
                }
                t1();
            </script>

    3.函数的参数(arguments对象)
      -arguments是表示函数的实际参数(与形参无关)

      -callee函数(回调函数属性)

      -arguments对象的秘密属性 callee属性。这个属性比较奇怪,它能够返回arguments对象所属的函数的引用、这相当于

    在自己的内部调用自己。用法:检测函数传递的参数正确与否。

    <script type="text/javascript" charset="utf-8">
                // js中 函数的参数分为:形参和实参
                function test(a, b, c, d) {
                    // 形参4个 实参2个,在js中 形参个数和实参个数没有关系
                    // 如何求形参的个数
                    test.length;
                    // 函数的实际参数,内部就是用一个数组去接受的
                    // arguments对象 可以访问函数的实际参数
                    // arguments对象 只能在函数的内部访问和使用
                    alert(arguments.length);
                    alert(arguments[0]);
                    alert(arguments[1]);
                    
                    if (test.length === arguments.length) {
                        return a + b;
                    } else {
                        return '参数不正确';
                    }
                    
                }
                alert(test(10, 20));
                
                // arguments对象  用的最多的地方还是做递归操作
                // callee方法 指向的是函数本身
                arguments.callee.length;// 等价于test.length
                
                
                function fact(num) {
                    if (num <= 1) {
                        return 1;
                    } else {
                        // 这里建议使用arguments.callee,因为可以存在这样的代码,fact = null,这样会出现问题
                        return num * arguments.callee(num - 1);
                    }
                }
                alert(fact(5));
            </script>

    4.this对象
      -this对象是在运行时基于函数的执行环境绑定的。在全局函数中,this等于window,而当函数被作为某个对象

    的方法调用时,this等于那个对象。

      -也就是说this关键字总是指代调用者。

      

    <script type="text/javascript" charset="utf-8">
                // this : this对象是指在运行时期,基于执行环境所绑定的。
                // 总是指向调用者
                var k = 10;
                function test() {
                    this.k = 20;
                }            
                alert(test.k); // 返回undefind,因为函数只是编译了,并没有执行
                test(); // 对于test来讲,执行环境是全局作用域  等价于window.test();
                alert(test.k);// 还是返回undefined,因为this指的是window
                alert(window.k); // 20 等价于alert(k);
            </script>

     5.call和apply方法

      - 每一个函数都包含两个非继承而来的方法:call和apply。

        这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

      -call,apply的用途之一就是传递参数,但事实上,他们真正强大的地方是能够扩充函数赖以运行的作用域。

      -使用call()和apply()来扩充作用域的最大好处就是对象不需要与方法有任何耦合关系。

      -call方法简单的实现。

    <script type="text/javascript" charset="utf-8">
                // call和apply 简单的用法,绑定一些函数,用于传递参数 调用
                function sum(x, y) {
                    return x + y;
                }
                
                function call1(num1, num2) {
                    // 将sum绑定到this。也就是call1上。这样就可以使用sum方法了。
                    return sum.call(this, num1, num2);
                }
                
                function apply1() {
                    // apply1和call类似,只不过后面传递的参数 是一个数组。
                    return sum.apply(this, [num1, num2]);
                }
                
                
                // 主要用途  扩充作用域
                window.color = 'red';
                var obj = {color :'blue'};
                
                function showColor(){
                    alert(this.color);
                }
                
                showColor.call(this);        // 结果为red
                showColor.call(obj);    // 结果为blue  函数showColor的作用域从 全局变为了obj
                
                // call方法的简单模拟和实现
                function test1(a, b) {
                    return a + b;
                }
                
                // 名字大写,默认为一个对象 ->自定义的对象
                function Obj(x, y) {
                    return x * y;
                }
                var obj1 = new Obj(10, 20);
                alert(test1.call(obj1, 10, 20));
                // 相当于 自己定义了一个临时的方法,用来接收test1
                obj.method = test1();
                // 使用完之后删掉
                delete obj1.method;
            </script>

    6.执行环境和作用域链概念
        -执行环境(execution context)是js中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行为。

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

      但是解析器在处理数据的时候会在后台执行它。

        -全局执行环境是最外围的一个执行环境。根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样。

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

      把控制权返还给之间的执行环境。当代码在一个环境中执行时,会创建变量对象的一个作用域链(Scope chain)。作用域链的用途,是保证

      对执行环境有权访问的所有变量和函数的有序访问。

    <script type="text/javascript" charset="utf-8">
                
                // 1.执行环境,window对象(最上层的执行环境)
                
                var color1 = 'blue';
                // 每个函数都有一个执行环境,(variable obj)
                function changeColor() {        
                    var color2 = 'red';
                    // color1 是一级作用域  color2是二级作用域,color3是三级作用域            
                    function swapColor() {         // 这个函数也产生了一个执行环境 (variable obj)
                        var color3 = color2;
                        color2 = color1;
                        color1 = color3;
                        // 这里可以访问color1,color2,color3
                    }
                    // 这里可以访问color1,color2,但是不能访问color3
                    swapColor();
                }
                // 这里只能访问color1
                changgeColor();        //第一个作用环境 window
                
                // 环境变量 可以一层一层的向上进行追溯,可以访问它的上层环境 (变量和函数),基于这种机制,全局变量尽量少用。节约效率。
            </script>

    7.垃圾收集和块级作用域
      -js是一门具有自动垃圾收集机制的编程语言。开发人员不必关心内存分配和回收问题。

        -离开作用域的值被自动标记为可以回收,因此将在垃圾收集期间被删除。标记清楚是目前主流的垃圾收集算法。这种算法的思想

      是想给当前不使用的值加上标记,然后回收其内存。

      -js里面没有块级作用域的概念,和C,java等高级语言不同。所以在使用if和for的时候要注意。

      -js模拟块级作用域。

    <script type="text/javascript" charset="utf-8">
                
                
                // 垃圾收集 方法1 标记法
                function test() {
                    var a = 10;    //被使用
                    var b = 20; // 被使用
                    
                }
                test();    //执行完毕之后,a,b又被标记了一次 , 标记成了没有被使用状态。
                
                // 方法2 引用计数法
                function test1() {
                    var a = 10;    // aCount = 1
                    var b = 20; // bCount = 1
                    var c;
                    c = a;    //aCount = 2
                    a = 20; //aCount = 1;
                    // 当aCount = 0的时候,就会被回收。                
                }
                
                // 块级作用域的概念
                function test2 () {
                    for (var i = 1; i <= 5; i++) {
                        alert(i);
                    }
                    alert(i); //在java中,肯定会报错,但是在js中  返回值为6.所以在使用时 需要注意这一点。原因是js没有块级作用域这一说法。
                    // js默认当函数 执行完之后  这个变量才没有。
                }
                
                
                // 模拟块级作用域
                function test3() {
                    // 写一个匿名函数,在加上小括号,表示让函数立即执行。
                    (function () {
                        for (var i = 1; i <= 5; i++) {
                        alert(i);
                    }
                    })();
                }
                
                // 函数直接执行 参考下面的代码
                (function() {alert('i am comming');})();
            </script>

    8.闭包(Closure)
      -闭包与函数之间有着紧密的关系,它是函数的代码在执行过程中的一个动态环境,是一个运行期的,动态的概念。

      -所谓闭包,是指词法表示包括不必计算的变量的函数。也就是说,该函数能够使用函数外显示定义的变量。

      -在程序语言中,所谓闭包。是指语法域位于某个特定的区域。具有持续参照(读写)位于该区域内自身范围之外的执行域上的非

    持久型变量值能力的段落。这些外部执行域的非持久性变量神奇保留他们在闭包最初定义(或创建)时的值。

    <script type="text/javascript" charset="utf-8">
                
                
                var name = 'xiao A';
                var obj = {
                    name : 'xiao B',
                    getName : function() {
                        return function(){
                            return this.name;
                        };
                    }
                };
                alert(obj.getName()());        // 结果为xiao A
                
                
                var obj1 = {
                    name : 'xiao B',
                    getName : function() {
                        return function(){
                            var o = this;
                            return o.name;
                        };
                    }
                };
                alert(obj1.getName()());    // 结果为xiao B
                
                // 闭包:一个函数可以访问另外一个函数作用域中的变量。
                // 封闭性,类似于java中的private  起一个保护变量的作用。
                
                // 1级作用域
                function f(x) {
                    // 2级作用域
                    var temp = x;
                    // 3级作用域
                    return function(x){
                        temp += x;
                        alert(temp);
                    };
                }
                var a = f(50);        // 匿名的函数结构体
                a(5);    // 55
                a(10);    // 65
                a(20);  // 85
                // 直到temo找不到了之后,才回收。
            </script>
  • 相关阅读:
    php开启伪静态(2转)
    php,apache伪静态(1转)
    sql 字段先计算后再拿比对的字段进行比对 效率提升100倍
    使用 PHP 读取文本(TXT)文件 并分页显示
    php给一张图片加上水印效果
    PHP命名空间(Namespace)的使用详解(转)
    php随机获取金山词霸每日一句
    网络报文分析利器eBPF
    这个世界变得有多复杂
    个人收藏网站推荐(一)
  • 原文地址:https://www.cnblogs.com/yangfanasp/p/7074798.html
Copyright © 2011-2022 走看看