对js闭包的一点理解

先看个简单的例子

function f1(){
    this.name = 'aaaa'
    return 'ddddd'
}

function f2(){
    return new String('ffffff')
}

function f3(){
    return function(){}
}

function f4(){
    return new function(){this.age=18}
}


这里是四种函数的返回类型:值、对象、函数、函数对象
也可以返回{},function(){}(),
但是{}也是对象,
function(){
}()返回的是函数里面返回的东西,要是进行探讨,又有上面的几种返回类型。故不作探讨了

1.返回值类型数据
return 'dddd'是返回字符串,值类型的字符串,这个没什么好说的,调用这个函数就得到一个字符串而已,但是new一个出来的话就不一样了

function f1(){
    this.name = 'aaaa'
    return 'dddd'
}
var a = f1()
var b = new f1()
console.log(a, b)
dddd f1 {name: "aaaa"}


也就是说一个返回值类型的函数,调用函数,得到的就是值类型数据
new函数,函数返回的是函数对象,并不能获取return的值。要想获取返回值怎么办
b.constructor()
输出:"dddd",
对于new出来的对象,这个函数是构造函数,再调用一遍构造函数不就可以了

2.返回对象
return new String('ffffff')是返回一个对象,这个对象是String函数构造出来的对象。

function f2(){
    return new String('ffffff')
}
var a = f2()
var b = new f2()
console.log(a, b)


输出String {"ffffff"} String {"ffffff"}
按上例来说,new function返回的应该是一个函数对象,这里为什么返回的是一个对象
可以先这么理解,一个构造函数返回的是对象,则调用构造函数返回的不是这个构造函数对象,而是构造函数返回的对象。
这才只是最基础的一种返回对象的方法,还可以有更多的扩充,后面再讲

3.返回函数
return function(){},函数也是对象,于是便跟return object一样了。不一样的是,return function(){}里面可以继续return。

function f3(){
    return function(){
        return 'aaaaaa'
    }
}
var a = f3()
var b = new f3()
console.log(a, b)

输出:两个f,没有换行
ƒ (){
    return 'aaaaaa'
} ƒ (){
    return 'aaaaaa'
}
如上,不管是否new返回的都是函数中return的函数,就跟第二例中一样都返回一个object。然后可以对返回的函数进行执行和new,执行就是a(),new就是new a()。于是又回到第二例的情况了。

4.返回函数对象
return new function(){this.age=18},函数对象也是对象,不同的是,如果执行var = f4(),相当于new function(),强行给执行函数变成new函数。

function f4(){
    return new function(){this.age=18}
}
var a = f4()
var b = new f4()
console.log(a, b)

输出:
{age: 18} {age: 18}

function f5(){
    return new function(){return 'ddddd'}
}
var a = f5()
var b = new f5()
console.log(a, b)

输出:
{} {}
如上,全部很诚实地返回了return的东西,并且是否new都一样

5.小扩展:开始看闭包
先看看return一个函数的情况

function fun(arg){
    var a = arg
    return function(){
        return a += 2
    }
}
var a =  fun('ddd')
var b = new fun(10)
console.log(a, b)

输出:
ƒ (){
    return a += 2
} ƒ (){
    return a += 2
}

其他执行输出:

a()
"ddd2"
a()
"ddd22"
b()
12
b()
14
按理来说,fun()执行后,函数代码块中的变量a就应该被释放掉了。
不过js有个叫做闭包的特性:
一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
什么情况下才会产生闭包呢:
作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
这就是闭包的产生。也就是说返回引用的话,返回时才会处于激活状态,才会有一个没有释放资源的栈区。
注意时返回引用,也就是object,也就是对象,不能时’dddd'、12、true这种值类型。

6.大扩展
简单复数上例的结论:函数返回引用时,函数处于激活状态,形成一个闭包

function Person(name,age){
    var _name = name
    var _age = age

    return {
        setName:function(newName){
            _name = newName
        },

        setAge:function(newAge){
            _age = newAge
        },

        show:function(){
            console.log('name : ' + _name + ' age : ' + _age)
        }
    }
}
var tom = new Person('Tom', 15)
tom.show()


输出:name : Tom age : 15

tom.setName('big tom')
tom.show()


输出name : big tom age : 15

怎么样,是不是有class的感觉,class本身也可以继承自function,class本身就是一个特殊的function
tom.name = 'aaaaa'
tom._name = 'bbbbb'
不会影响show的输出

关于返回值的不同,主要区分与值类型和引用类型(也就是对象,new String,{},function),值类型和引用类型也是比较有趣的东西,可以研究研究

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值