比如:
function main(){
return function inner(){}
}
每次调用 main 方法,都返回一个新的 inner,但是这个 inner 会重新创建吗?
或者说,调用两次后,内存中有几个 inner 函数被创建出来?
每次调用main后,都返回一个新的 inner。 return function … 其实就是 return (new Function(’…’)); 另外,内存中也并不是简单的 “多份 inner 函数”,而是多份包含了inner()上下文的闭包。
@myy 多份上下文闭包肯定是必要的,但是感觉多份 inner 函数有点不舒服(不是对结果的怀疑,还是对设计的不解)
比如,如果“内存有多份 inner 函数”,那
class A{
inner(){}
}
就会比
function A (){
return {
inner(){}
}
}
省内存了(有多个 A 实例时)。
但第二种写法,不用关心 this 的指向问题,反而比“先进”的 class 关键字更舒服。
class A 多个实例虽然共用了 inner(),但是A本身同样是多份啊。。也没省啥内存。
@myy 多实例,共用一个 __proto__,也就是 A.prototype
class A {
go(){ console.log(1) }
}
const x = new A()
const y = new A()
x.go() // 1
y.go() // 1
const oldGo = x.go
console.log(oldGo == A.prototype.go)
A.prototype.go = function (){ console.log(2) }
const z = new A()
z.go() // 2
x.go() // 2
y.go() // 2
const newGo = x.go
console.log(newGo == A.prototype.go)
console.log(newGo != oldGo)
会返回多个函数的闭包对象 测试代码如下:
function main() {
return function inner() { }
}
const array = [];
for (let i = 0; i >= 0; i++) {
const fn = main();
array.push(fn);
}
相比之下,你的第二种方式只会增加引用本身,确实会更节省内存,实际上这也是单例模式的优势之一
测试代码:
class A {
go() { console.log(1) }
}
const x = new A()
const array = [];
for (let i = 0; i >= 0; i++) {
array.push(x.go);
}
@hyj1991 你用的什么工具啊老兄,看起来很棒的样子
@hyj1991 class 的形式虽然没有闭包对象,但有实例啊
打印 go 的话,看不到实例占用的内存,但在上下文方面,两种形式应该差别不大
还有个问题要请教一下(因为上面的没看懂……)
是不是说 function main(){ return function inner(){} }
这种形式,只增加闭包,而不重新创建 inner?
工具是这个:https://github.com/hyj1991/easy-monitor
截图是我还在开发中的堆快照本地分析功能,拿来试了下你的这个问题。
是不是说 function main(){ return function inner(){} } 这种形式,只增加闭包,而不重新创建 inner?
是的,你看上面两个测试都是创建了100w次函数,所以两者的引用大小(object elements)是一样的 9.95MB,但是前者会额外多100w个闭包对象,导致内存占用大大超过后者
@hyj1991 感谢~ 但是,new A() 也会创建同样数量的实例的,内存占用应该也很大~