js 進階

1. 靜態成員和實例成員

靜態成員表示的是靜態方法和靜態屬性的概念,所謂的靜態,就是由構造函數所提供的。

實例成員表示的是實例方法和實例屬性,所謂的實例就是由構造函數所創建的對象。

一般工具型方法都是由靜態成員提供,一般與實例對象有關的方法由實例成員表示。

2. 函數的構造函數Function

Function的存在目的是動態創建函數。

在js中使用Function可以實例化函數對象,也就是說在js中,函數與普通對象一樣,也是一個對象類型,可以使用對象的動態特性,可以利用構造函數創建函數,可以創建其他對象,函數是js中的一等公民,是唯一可以限定變量作用域的結果。

new Function( agr0,arg1,arg2,......,argN,body);Function中的參數全部是字符串,該構造函數的作用是將參數鏈接起來組成函數,如果參數只有一個,那麼表示函數體;如果參數有多個,那麼最後一個參數表示函數體,前面的所有參數表示函數的參數;如果沒有參數,表示創建一個空函數。

<script type="text/javascript">
    function foo(){ console.log('Hello'); } // 傳統寫法
    var func = new Function( 'console.log("Hello");' ); // 與上面等價,注意參數爲字符串

    function foo(){}
    var func = new Function();

    function foo(num) {console.log(num);}
    var func = new Function('num',"console.log(num);"); // 注意參數的表示

    // 任意的一個函數,都是相當於Function的實例,類似於{}與new Object()的關係
    function foo(){} // 告訴解釋器,有一個對象叫foo,是一個函數,相當於new Function()得到一個函數對象
    // 函數應有_proto_屬性,其構造函數是Function,函數應繼承自Function.prototype,Function.prototype繼承自Object.prototype
</script>

函數都是Function的實例,故Object函數是Function的一個實例,Object作爲對象是繼承自Function.prototype的,Function是自己的構造函數。

3. 函數原型鏈結構

4. Function原型鏈結構

在js中,任何對象的老祖宗都是Object.prototype,任何函數的老祖宗都是Function.prototype。

5. eval() 函數

計算 JavaScript 字符串,並把它作爲腳本代碼來執行,如果參數是一個表達式,eval() 函數將執行表達式;如果參數是Javascript語句,eval()將執行 Javascript 語句。

<script>
    eval("x=10;y=20;document.write(x*y)"); // 200
    document.write("<br>" + eval("2+2")); // 4
    document.write("<br>" + eval(x+17)); // 27

    // 將{}解釋成代碼塊,name:數據,將:解釋稱標記語言
    console.log(eval( "{name: 'Karry'}" ) ); // Karry

    console.log(eval("({name: 'Karry', age: 19})")); // 返回對象,()將數據轉換成表達式
</script>

6. 詞法作用域&作用域鏈

(1)詞法作用域概念:代碼在編寫過程中體現出來的作用範圍,代碼一旦寫好,不用執行,作用範圍就已經確定好了。

(2)作用規則:函數允許訪問函數外的數據;整個代碼結構中只有函數可以限定作用域,塊{}不限定作用域;作用規則首先使用提升規則分析;如果當前作用域中有名字了,就不考慮外面的名字。

(3)作用域鏈概念:代碼至少有一個作用域即全局作用域,如果代碼中有函數,則又構成一個作用域,將所有作用域列出來,可以有一個結構,函數內指向函數外的鏈式結構。

(4)作用域鏈圖:圖中一個方塊代表一個聲明。

<script>
    var num = 123;
    function f1() {
        console.log(num);
    }
    function f2() {
        var num = 456;
        f1(); // 此處是調用
    }
    f2(); // 123
</script>

7. 閉包

(1)概念:一個具有封閉的、對外不公開的包裹結構或空間,在js中函數可以構成閉包,不允許外界直接訪問,一般用於保護私有數據。

(2)訪問閉包裏面數據的示例

<script type="text/javascript">
    function foo() {
        var num = Math.random();
        function func(){return num;}
        return func;
    }
    var f = foo(); // f直接訪問num
    var res1 = f(); // 0級鏈無法訪問1級鏈的數據,所以間接的0級鏈操作2級鏈的函數,來訪問1級鏈的數據
    var res2 = f(); // 與res1相等
</script>

(3)函數科裏化(高階函數):定義一個函數,該函數返回一個函數。

<script>
    function foo( arg1 ) {
        function func( arg2 ) {}
        return func;
    }
    foo( arg1 )( arg2 );
</script>

(4)閉包的應用

<script>
    function foo() {
        var num1 = Math.random();
        var num2 = Math.random();
        return { // 獲得超過一個數據,封裝成對象
            num1: function(){ return num1; },
            num2: function(){ return num2; }
        };
    }
</script>
<script>
    function foo() {
        var num = Math.random();
        return {
            get_num: function() { return num; }, // 獲取函數中的數值
            set_num: function( value ) { num = value; } // 設置函數中的數值
        }
    }
    var o = foo();
    var num = o.get_num();
    o.set_num(0.4);
</script>

(5)閉包的性能問題:函數執行需要內存,那麼函數中定義的變量,會在函數執行結束後自動回收,凡是因爲閉包結構被引出的數據,如果還有變量引用這些數據的話,那麼這些數據就不會被回收,因此在使用閉包的時候,如果不使用某些數據了,一定要賦值null。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章