JS面向對象之閉包

閉包

閉包的概念

  • 閉包的含義就是閉合,簡單來講就是一個具備封閉功能的結構
  • 閉包就是具備封閉的對外不公開的,包裹結構或空間

在 js 中的閉包

  • 在 js 中函數能夠構成閉包
  • 函數是一個代碼結構的封閉結構,具備包裹特性
  • 根據做用域規則, 只容許函數訪問外部數據, 外部沒法訪問函數內部數據
  • 因此說函數具備封閉的, 不公開的特效, 因此能夠構成閉包

閉包解決什麼問題

  1. 閉包不容許外界訪問
  2. 外界間接訪問閉包中的數據
    • 函數能夠構成閉包, 解決的問題就是函數外訪問到函數內部的數據

獲得一個數據

function foo(){
        var num = 123;
        return num;
    }
    var result = foo();
    console.log(result);
}
  1. 外部能夠訪問到函數內的數據
  2. 可是數據不能進行二次訪問, 若是再試訪問函數內部數據須要再次調用函數, 雖然獲得的移入是num = 123, 可是實際不是第一次函數調用的那個值

獲得一個函數, 經過函數訪問數據

  • 在函數內的數據, 不能直接被函數外訪問,若是函數內再定義一個函數, 那麼函數內部數據能夠被函數外訪問
function foo(){
        var num = Math.random();
        function fn(){
            return num;
        }
        return fn;
    }
    var f = foo();
    // f 能夠直接訪問這個數據 num
    var result1 = f();
    var result2 = f();
    // 獲得結果一致,說明屢次訪問的是同一個數據

獲得的數據能夠是對象

function foo(){
        var  o = {name : 'Bob'};
        return function(){
            return o;
        }
    }
    var fn = foo();
    var result = fn();

得到多個數據

function foo(){
        var num1 = Math.random();
        var num2 = Math.random();
        return {
            num1 : function(){
                return num1;
            },
            num2 : function(){
                return num2;
            }
        }
    }

得到和修改這個數據

function foo(){
        var num = Math.random();
        return {
            getNum : function(){
                return num;
            },
            setNum : function(value){
                num = value;
            }
        }
    }

閉包的基本結構

  1. 經過函數: 寫一個函數, 函數內定義一個新函數, 返回新函數, 使用新函數獲得函數內的數據
  2. 經過對象: 寫一個函數, 函數內頂一個對象, 對象中綁定多個方法, 返回對象, 利用對象內的方法訪問函數內中的數據

閉包的基本用法

  1. 帶有私有訪問數據的對象
function Person(){
        this.name = 'Peter';
        // setName('')
    }
    // 私有數據指的是隻有函數內部能夠訪問的數據,或者對象內部的方法

    // 簡單的例子,判斷孩子是否是老張家的
    function createPerson(){
        var name = '張全蛋';
        return {
            getName : function(){
                return name;
            },
            setName : function(value){
                // 若是value的第一個字符串是 張 ,就設置
                if(value.charAt(0) === '張'){
                    name = value;
                } esle {
                    //不姓 張 ,就將錯誤拋出
                    throw new Error('你不姓張,難道還能姓王?');
                }
            }
        }
    }
  1. 帶有私有數據的函數
// 不具備私有數據
    var fn = function(){};
    function fn(){}

    // 具備私有數據
    var foo = (function(){
        // 私有數據
        return function(){
            // 能夠訪問私有數據
        }
    })();

閉包的基本模型

函數模型

function foo(){
    // 私有數據
    return function(){
        // 能夠訪問上面的私有數據
    }
}

對象模型

function foo(){
    // 私有數據
    return {
        method : function(){
            // 能夠訪問的私有數據
        }
    }
}

閉包的性能問題

  • 函數的執行須要內存, 函數中定義的變量會在函數執行後自動回收
  • 由於是閉包結構, 若是還有變量引用這些數據的話, 這些數據不會被回收
  • 所以在使用閉包的時候,若是不使用這些數據了, 須要將函數賦值爲 null
var foo = (function(){
        var num = 123;
        return function(){
            return num;
        }
    })();
    // 若是不須要foo中的數據, 賦值爲 null
    foo = null;
相關文章
相關標籤/搜索