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()
        }
    }
}();

如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有数据的方法,那么就可以使用模块模式。

猜你喜欢

转载自blog.csdn.net/XiaoHuangDiLHD/article/details/83013665
今日推荐