javascript基礎——函數表達式

函數聲明與函數表達式的區別:

函數聲明提升:就是使用函數聲明時,函數會被解析器先讀取,以供執行環境使用,所以函數聲明的位置可以在函數調用的後面

函數表達式則不可以在函數調用的前面,必須先定義函數表達式,纔可以調用,不然瀏覽器會報錯。

函數表達式:


var sayHi = function(name){
    console.log(name+",hi");
}

sayHi("john")

函數表達式創建的是一個匿名函數。然後將匿名函數賦值給一個變量,通過變量來調用。

(function(name){
    console.log(name+",hi");
})("john")


(function(name){
    console.log(name+",hi");
}("john"))

這兩種執行方式效果是相同的,是立即執行的意思,定義完之後直接執行,而不需要通過一個變量+()來調用。

閉包:

按照高程裏面的描述就是:一個函數可以訪問另外一個函數作用域裏面的變量。

function outerSum(a,b){
    var sum = function(){
        return a+b
    }
    return sum;
}

var result = outerSum(1,2)
result() // 3

函數調用時發生的事情:

首先會創建一個執行環境和相應的作用域鏈,然後使用arguments和其他命名參數的值來初始化函數的活動對象。然後外部函數的活動對象始終是第二個。

這是最簡單的閉包,sum內部函數可以獲取outerSum外部函數的活動變量。當outerSum執行完畢之後,它的執行環境被銷燬了,但是它的活動對象依然在內存中,沒有被銷燬,因爲匿名函數依然在引用着這些變量。直到匿名函數被銷燬,它的活動對象纔會被銷燬。

閉包的缺點:

function a() {
    var arr = []

    for(var i = 0;i < 10; i++){
        arr[i] = function() {
           console.log(i)
        }
    }
    return arr
}

var b = a()
b[0]() //10
b[1]() //10
b[2]() //10

閉包只能取得包含函數中任何變量的最後一個值。比如這個例子。程序中先執行a(),這個函數,但是b()並沒有被調用。直到執行到return arr這條語句,a()已經執行完成,然後接下來繼續往下執行,就是b[0]()這個方法,但此時i=10,所以打印出來的都是10。可以把匿名函數設置爲立即執行函數,這樣就可以解決這個問題了。

function a() {
    var arr = []

    for(var i = 0;i < 10; i++){
        arr[i] = function(num) {
            return function(){
                console.log(num) 
            }     
        }(i)  
    }
    return arr
}

var b = a()
b[0]() //0
b[1]() //1
b[2]() //2

關於this對象

var name = 'The window'

var object = {
    name: "My Object",

    getNameFunc: function(){
        return function(){
            return this.name
        }
    }
}

console.log(object.getNameFunc()()) //The Window

這裏相當於:

var a = object.getNameFunc()
console.log(a())

這裏的a()是在全局作用域下調用的,並且不是dot調用,所以this就指向window。只要函數中指定this的值就可以了。

var name = 'The window'

var object = {
    name: "My Object",

    getNameFunc: function(){
        var that = this
        return function(){
            return that.name
        }
    }
}

console.log(object.getNameFunc()()) // My Object
var name = 'The window'

var object = {
    name: "My Object",

    getNameFunc: function(){
        return function(){
            return this.name
        }.bind(object)()
    }
}

console.log(object.getNameFunc()) 
console.log(object.getNameFunc().call(object))
console.log(object.getNameFunc().apply(object))

只要修改this的值是指向object就可以返回object裏面的值。

模仿塊級作用域:

(function () {
    //塊級作用域
}) ()

 這是一個立即執行函數,模仿塊級作用域,其他作用域無法訪問這個作用域。

function() {

} () // 錯誤的寫法

這是個函數聲明,函數聲明後面加括號是錯誤的做法,函數聲明後面不能加圓括號。只有函數表達式纔可以。我們只要給函數聲明用圓括號括起來,那麼就可以轉換爲函數表達式。就像上面的形式那樣。

優點:模仿塊級作用域可以減少閉包占用的內存問題,因爲沒有指向匿名函數的引用,只要函數執行完畢,就可以立即銷燬其作用域鏈。

模塊模式:

爲單例創建私有變量和特權方法。所謂的單例,指的就是隻有一個實例的對象。

var singleton = function() {
    //私有屬性和方法
    var privateVariable = 10;

    function privateFunction(){
        return privateVariable;
    }

    return {
        //公有方法和屬性                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
        publicVariable: true,

        publicMethods:function() {
            privateVariable++;
            return privateFunction()
        }
    }
}();

如果必須創建一個對象並以某些數據對其進行初始化,同時還要公開一些能夠訪問這些私有數據的方法,那麼就可以使用模塊模式。

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