zoukankan      html  css  js  c++  java
  • 重温Javascript(四)-函数

    函数


      函数声明提升,在执行代码之前会先读取函数声明

    sayHi();
    
    function sayHi(){
        alert("Hi!");
    }

    递归


      arguments.callee是指向正在执行的函数的指针

      还可以换种方式达成一样的效果

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

    函数执行的作用域链


    function compare(value1, value2){
        if (value1 < value2){
            return -1;
        } else if (value1 > value2){
            return 1;
        } else {
            return 0;
        }
    }
    
    var result = compare(5, 10);

      先定义了compare()函数,又在全局作用域调用它。当调用时,会创建一个包含arguments、value1、value2的活动对象。全局执行环境的变量对象(包含result和compare)在compare()执行环境的作用域中处于第二位

      作用域链本质上是一个指向变量对象的指针列表,只引用但不实际包含变量对象

      

      

    闭包


      闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见方式,在一个函数内部创建另一个函数  

    function createComparisonFunction(propertyName) {
        return function(object1, object2){
            var value1 = object1[propertyName];
            var value2 = object2[propertyName];
            if (value1 < value2){
                return -1;
            } else if (value1 > value2){
                return 1;
            } else {
                return 0;
            }
        };
    }
    var compare = createComparisonFunction("name");
    var result = compare({ name: "Nicholas" }, { name: "Greg" });

      

      在匿名函数从 createComparisonFunction()中被返回后,它的作用域链被初始化为包含createComparisonFunction()函数的活动对象和全局变量对象。这样,匿名函数就可以访问在createComparisonFunction()中定义的所有变量。createComparisonFunction()

    函数在执行完毕后,其活动对象也不会被销毁,因为匿名函数的作用域链仍然在引用这个活动对象。换句话说,当createComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但它的活动对象仍然会留在内存中;直到匿名函数被销毁后,createComparisonFunction()的活动对象才会被销毁

    //创建函数
    var compareNames = createComparisonFunction("name");
    
    //调用函数
    var result = compareNames({ name: "Nicholas" }, { name: "Greg" });
    
    //解除对匿名函数的引用(以便释放内存)
    compareNames = null;

      创建的比较函数被保存在变量compareNames 中。而通过将compareNames 设置为等于null解除该函数的引用,就等于通知垃圾回收例程将其清除。随着匿名函数的作用域链被销毁,其他作用域(除了全局作用域)也都可以安全地销毁了。

      

    闭包与变量


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

      每个函数都返回10。因为每个函数的作用域链中都保存着createFunctions() 函数的活动对象, 所以它们引用的都是同一个变量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;
    }

    闭包与this,arguments


      每个函数在被调用时都会自动取得2个特殊变量:this和arguments。内部函数在搜索这2个变量时,只会搜索到其活动对象为止,不能直接访问外部函数中的这2个变量。把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以访问了。arguments也是如此。

    var name = "The Window";
    
    var object = {
        name : "My Object",
        getNameFunc : function(){
            var that = this;
            return function(){
                return that.name;
            };
        }
    };
    
    alert(object.getNameFunc()()); //"My Object"    

    模仿块级作用域


    function outputNumbers(count){
        for (var i=0; i < count; i++){
            alert(i);
        }
        alert(i); //计数
    }

      通常称为私有作用域  

    (function(){
        //这里是块级作用域
    })();
    function outputNumbers(count){
        (function () {
            for (var i=0; i < count; i++){
                alert(i);
            }
        })();
    
        alert(i); //导致一个错误!
    }

    私有变量


      

    function MyObject(){
        //私有变量和私有函数
        var privateVariable = 10;
    
        function privateFunction(){
            return false;
        }
    
        //特权方法
        this.publicMethod = function (){
            privateVariable++;
            return privateFunction();
        };
    }
    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"

      

    静态私有变量


      

    (function(){
    
        //私有变量和私有函数
        var privateVariable = 10;
        function privateFunction(){
            return false;
        }
    
        //构造函数
        MyObject = function(){
        };
    
        //公有/特权方法
        MyObject.prototype.publicMethod = function(){
            privateVariable++;
            return privateFunction();
        };
    
    })();

      未经声明的变量,会创建一个全局变量

      但使用prototype的问题时实例变量需要自己定义

      

    (function(){
    
        var name = "";
    
        Person = function(value){
            name = value;
        };
    
        Person.prototype.getName = function(){
            return name;
        };
    
        Person.prototype.setName = function (value){
            name = value;
        };
    })();
    
    var person1 = new Person("Nicholas");
    alert(person1.getName()); //"Nicholas"
    person1.setName("Greg");
    alert(person1.getName()); //"Greg"
    
    var person2 = new Person("Michael");
    alert(person1.getName()); //"Michael"
    alert(person2.getName()); //"Michael"

    模块模式


      单例对象  

    var singleton = {
        name : value,
        method : function () {
        //这里是方法的代码
        }
    };

      模块模式通过为单例添加私有变量和特权方法使其得到增强

    var singleton = function(){
    
        //私有变量和私有函数
        var privateVariable = 10;
    
        function privateFunction(){
            return false;
        }
    
        //特权/公有方法和属性
        return {
            publicProperty: true,
            publicMethod : function(){
                privateVariable++;
                return privateFunction();
            }
        };
    }();

      以这种模式创建的每个单例都是Object的实例,因为最终要通过一个对象字面量来表示它。单例通常作为全局对象存在,不会将它传递给一个函数,不会使用instanceOf来检查其对象类型

    增强的模块模式


      在返回对象之前加入对其增强的代码。适合的场景是单例必须是某种类型的实例,还必须添加某些属性或方法对其增强。

    var singleton = function(){
    
        //私有变量和私有函数
        var privateVariable = 10;
        function privateFunction(){
            return false;
        }
    
        //创建对象
        var object = new CustomType();
        //添加特权/公有属性和方法
        object.publicProperty = true;
    
        object.publicMethod = function(){
            privateVariable++;
            return privateFunction();
        };
    
        //返回这个对象
        return object;
    }();

    引用:

    《JavaScript高级程序设计中文版》

  • 相关阅读:
    ui优化
    《行尸走肉:行军作战》移动端优化经验
    Git master branch has no upstream branch的解决
    在线压图
    Git 分支管理-git stash 和git stash pop
    ScriptableObject
    Git解决pull无法操作成功
    Unity自带IAP插件使用(googleplay)
    Unity苹果(iOS)内购接入(Unity内置IAP)
    VMWare 装mac os x 一个必备优化神器 beamoff
  • 原文地址:https://www.cnblogs.com/dopeter/p/6661945.html
Copyright © 2011-2022 走看看