js 构造函数和闭包的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
QGabriel
V2EX    Javascript

js 构造函数和闭包的问题

  •  
  •   QGabriel 2022-01-26 12:04:46 +08:00 3036 次点击
    这是一个创建于 1428 天前的主题,其中的信息可能已经有所发展或是发生改变。
    function Foo(){
    var a = 1
    this.get = function(){
    console.log(a)
    }
    this.add = function () {
    a++
    }
    }

    let foo1 = new Foo()
    let foo2 = new Foo()
    foo1.add()
    foo1.get() // 2
    foo2.get() // 1

    function C(){
    var a = 1
    return function () {
    return a++
    }
    }

    let c1 = C()
    let c2 = C()
    c1() // 2
    c2() // 2

    问题 1: 构造函数内部声明变量只能通过实例方法调用,这和闭包是一样的吗?
    17 条回复    2022-01-26 16:55:59 +08:00
    charlie21
        1
    charlie21  
       2022-01-26 12:23:27 +08:00
    https://www.ruanyifeng.com/blog/2009/08/learning_Javascript_closures.html
    搜关键字 内存,理解一下闭包对内存的影响
    QGabriel
        2
    QGabriel  
    OP
       2022-01-26 12:35:18 +08:00
    @charlie21 构造函数的方式和闭包不是一回事吗?
    zythum
        3
    zythum  
       2022-01-26 12:49:13 +08:00
    你这种情况,大体是一样的。每一个实例都是使用自己创建的 add 方法。一般来说你下面的情况叫工厂函数。

    但是上面的情况,大概应该写成这样就不一样的。
    function Foo() {
    this.a = 1;
    }
    Foo.prototype.add = function () {
    this.a++;
    }
    每个 Foo 实例是共用 prototype 上的 add 方法的。
    rabbbit
        4
    rabbbit  
       2022-01-26 13:06:08 +08:00
    上边那个构造函数大概可以理解成: 

    function Foo() {
      var obj = {};
      var a = 1;

      obj.get = function () {
       console.log(a);
     };
      obj.add = function () {
       a++;
     };
      return obj;
    }

    let foo1 = Foo()
    QGabriel
        5
    QGabriel  
    OP
       2022-01-26 13:18:15 +08:00
    @rabbbit 构造函数的方式是闭包吗?
    cheots
        6
    cheots  
       2022-01-26 13:19:46 +08:00 via iPhone
    rabbbit
        7
    rabbbit  
       2022-01-26 13:21:04 +08:00
    要我个人理解 this.get/this.add 对 var a 的引用算闭包
    mozhizhu
        8
    mozhizhu  
       2022-01-26 13:52:15 +08:00
    c1 和 c2 在内存索引上是同一个
    mozhizhu
        9
    mozhizhu  
       2022-01-26 13:52:53 +08:00
    @mozhizhu 卧槽,今日不宜回复,老是看错
    2i2Re2PLMaDnghL
        10
    2i2Re2PLMaDnghL  
       2022-01-26 14:04:07 +08:00
    构造函数的区别是 prototype 可以共用,其他并无影响。
    我仍然不推荐称呼闭包,闭包是一种__实现__而不是__语法__。这种语法叫做「词法作用域」。
    2i2Re2PLMaDnghL
        12
    2i2Re2PLMaDnghL  
       2022-01-26 14:33:47 +08:00
    @KuroNekoFan 当然不是,一种语法和一种实现的技术当然不是一回事。
    实际上被称为闭包的实体,就是那个可以 xxx() 的东西。你已经找不到函数本身了。
    就算是 new Function 出来的也是个闭包,只是父级域不是当前域而是全局域来着。
    KuroNekoFan
        13
    KuroNekoFan  
       2022-01-26 14:52:44 +08:00
    @2i2Re2PLMaDnghL 嗷我我误会了,楼主这个确实更能体现 lexical scope 的特性而不是闭包
    QGabriel
        14
    QGabriel  
    OP
       2022-01-26 15:06:19 +08:00
    @2i2Re2PLMaDnghL 你意思是说只有函数本身消失了但其作用域还在的方式叫闭包?构造函数那种不算闭包吗?
    2i2Re2PLMaDnghL
        15
    2i2Re2PLMaDnghL  
       2022-01-26 16:03:46 +08:00
    @QGabriel 不是函数本身消失了,而是封在闭包里;并且在现在大部分支持闭包的语言中,你找不到函数本身,只能找到包含这个函数的闭包。你几乎不可能生成函数的引用,只能生成闭包的引用;你也无法直接调用函数,只能调用闭包让闭包去调用函数。
    但因为这个闭包是 first-class function 的一个实例,也是你唯一可以找来调用的东西,所以实际上大部分人在所有时间并且所有人在大部分时间还是称闭包为函数。

    至于你#14 的这句话,因为太过混乱我甚至不知道从哪开始回复。
    你根本拿不到函数,因为函数早已被(编译器、解释器)封装进闭包。
    除非你能想办法把让这段代码返回 true

    (function(){
    var a = {};
    // create something called new_get with foo1.get
    return a===new_get()
    })
    codermagefox
        16
    codermagefox  
       2022-01-26 16:16:54 +08:00
    真无聊..
    pendulum
        17
    pendulum  
       2022-01-26 16:55:59 +08:00
    你运行过了吗?我的运行结果是 2 1 1 1
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4858 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 03:56 PVG 11:56 LAX 19:56 JFK 22:56
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86