js 构造函数和闭包的问题

2022-01-26 12:04:46 +08:00
 QGabriel
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: 构造函数内部声明变量只能通过实例方法调用,这和闭包是一样的吗?
2383 次点击
所在节点    JavaScript
17 条回复
charlie21
2022-01-26 12:23:27 +08:00
https://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
搜关键字 内存,理解一下闭包对内存的影响
QGabriel
2022-01-26 12:35:18 +08:00
@charlie21 构造函数的方式和闭包不是一回事吗?
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
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
2022-01-26 13:18:15 +08:00
@rabbbit 构造函数的方式是闭包吗?
cheots
2022-01-26 13:19:46 +08:00
rabbbit
2022-01-26 13:21:04 +08:00
要我个人理解 this.get/this.add 对 var a 的引用算闭包
mozhizhu
2022-01-26 13:52:15 +08:00
c1 和 c2 在内存索引上是同一个
mozhizhu
2022-01-26 13:52:53 +08:00
@mozhizhu 卧槽,今日不宜回复,老是看错
2i2Re2PLMaDnghL
2022-01-26 14:04:07 +08:00
构造函数的区别是 prototype 可以共用,其他并无影响。
我仍然不推荐称呼闭包,闭包是一种__实现__而不是__语法__。这种语法叫做「词法作用域」。
KuroNekoFan
2022-01-26 14:16:14 +08:00
2i2Re2PLMaDnghL
2022-01-26 14:33:47 +08:00
@KuroNekoFan 当然不是,一种语法和一种实现的技术当然不是一回事。
实际上被称为闭包的实体,就是那个可以 xxx() 的东西。你已经找不到函数本身了。
就算是 new Function 出来的也是个闭包,只是父级域不是当前域而是全局域来着。
KuroNekoFan
2022-01-26 14:52:44 +08:00
@2i2Re2PLMaDnghL 嗷我我误会了,楼主这个确实更能体现 lexical scope 的特性而不是闭包
QGabriel
2022-01-26 15:06:19 +08:00
@2i2Re2PLMaDnghL 你意思是说只有函数本身消失了但其作用域还在的方式叫闭包?构造函数那种不算闭包吗?
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
2022-01-26 16:16:54 +08:00
真无聊..
pendulum
2022-01-26 16:55:59 +08:00
你运行过了吗?我的运行结果是 2 1 1 1

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/830694

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX