• JS高程3:函数表达式


    定义函数的方式有2种:

    • 函数声明
    • 函数表达式

    函数声明是最常用的,函数声明的一个特征就是:在执行代码之前,就已经读取了函数声明。

    这个特征还有一个专门的术语:函数声明提升

    递归函数

    所谓递归函数,就是在函数体中使用函数本身。

    这就需要用到arguments.callee,他总是指向正在执行的函数,不论函数名怎么改变。

    function factorial(num){
        if (num <= 1){
            return 1;
    } else {
            return num * arguments.callee(num-1);
    }
    }
    var anotherFactorial = factorial;
    factorial = null;
    alert(anotherFactorial(4));
    

     上面的例子,如果将arguments.callee改为factorial,就会报错!因为函数名称改变了。

    但是,在严格模式下,上面的例子还是错误的!因为严格模式没有arguments.callee这个属性。

    需要使用命名函数表达式来解决:

    var factorial = (function f(num){
        if (num <= 1){
            return 1;
    } else {
            return num * f(num-1);
    }
    });
    var anotherFactorial = factorial;
    factorial = null;
    alert(anotherFactorial(4));
    

     像这样的,不论严格模式,都能成功执行。

    闭包

    复习:作用域链的本质就是一个包含指向变量对象的指针列表。每个执行环境都对应着一个变量对象。

    全局变量对象会一直存在,而活动变量对象在函数执行完成就会被销除。

    闭包和匿名函数非常容易弄混淆,其实他们很不一样。

    闭包是函数没错,但是他是可以访问其他函数作用域中变量的函数。

    所以就有人说了,那么内部函数不就是闭包么?这个不太正确。因为闭包,一般会将闭包本身返回,

    或者将闭包赋值给一个变量,然后返回这个变量。而内部函数不一定会返回本身。

    先来看一个例子:

    function createFunctions(){
        var result = new Array();
        for (var i=0; i < 10; i++){
            result[i] = function(){
                return i;
            };
        }
        return result;
    }
    

     这个数组中,位置1的函数会返回10,其实是所有元素都会返回10。为什么呢?因为所有元素都是匿名函数:

    ƒ (){
                return i;
            }
    

     而当你调用这个函数时,变量i的值就是10。

    如果想实现期望的效果,可以这样做,在每次循环后,将i的值记录下来并返回:

    function createFunctions(){
        var result = new Array();
        for (var i=0; i < 10; i++){
            result[i] = function(num){
                return function(){
                    return num;
                };
        }(i);
    }
    return result;
    }
    

     像这样,变量num每次的值都是不一样的。

    关于闭包的另一个问题就是,函数中的变量始终会保留在内存中,而不是像通常的那样被销除:

    function f1(){
    
        var n=999;
    
        nAdd=function(){n+=1}
    
        function f2(){
          alert(n);
        }
    
        return f2;
    
      }
    
      var result=f1();
    
      result(); // 999
    
      nAdd();
    
      result(); // 1000
    

     上面,变量n在函数执行完毕后,还是在内存中,所以才有1000的返回。

    关于this和arguments

    一般来说,内部函数是能够访问外部函数的变量对象的,即能够访问外部作用域中的所有变量。

    但是,this和arguments是例外,内部函数在搜索这2个变量时,只会搜索到本身的活动对象为止,

    所以外部函数的this和arguments变量。内部函数是不能够访问的。

    但是注意,全局环境中的this和arguments是可以访问的。

    ar name = "The Window";
    var object = {
        name : "My Object",
        getNameFunc : function(){
            return function(){
                return this.name;
            };
        }
    };
    alert(object.getNameFunc()()); //"The Window"(在非严格模式下)
    

     这就是为什么,最后返回的值是"The Window"而不是"My Object"。

    模仿块级作用域

    块级作用域也叫做私有作用域。

    一般来说,实际开发中应该尽量避免过多的在全局环境中定义变量和函数,这个时候私有作用域的价值就体现出来了!

    (function(){
        var now = new Date();
        if (now.getMonth() == 0 && now.getDate() == 1){
                alert("Happy new year!");
        }
    })();
    

     把上面这段代码放在全局作用域中,可以用来确定哪一天是 1 1 日;如果到了这一天,就会向用
    户显示一条祝贺新年的消息。其中的变量 now 现在是匿名函数中的局部变量,而我们不必在全局作用域
    中创建它。

    私有变量

     私有变量有:函数的参数,局部变量和内部函数。

    可以访问私有变量的方法就叫做特权方法,一般创建特权方法的方式是通过闭包来实现。

    function Person(name){
        this.getName = function(){
            return name;
        };
        this.setName = function (value) {
            name = value;
        };
    }
    var person = new Person("Nicholas");
    alert(person.getName()); //"Nicholas"
    person.setName("Greg");
    alert(person.getName()); //"Greg"
    
  • 相关阅读:
    python——数据库操作
    【笔试】T实习生2014 总结
    【JS】Intermediate6:jQuery
    【JS】Intermediate5:Scope
    【JS】Intermediate4:JSON
    【JS】Intermediate3:AJAX
    【JS】Intermediate2:Events and Callbacks
    【JS】Intermediate1:The DOM
    【JS】Beginner9:Arrays
    【JS】Beginner8:Objects
  • 原文地址:https://www.cnblogs.com/leomei91/p/7542208.html
Copyright © 2020-2023  润新知