为什么 javascript 函数每次调用都有实例?
Why javascript function has instance per call?
javascript介绍说:
当我有如下代码时:
var Person=function(name){
this.name=name;
this.sayHello=function(){return 'Hello '+name;}
}
每当我实例化一个"Person"时,内存中就会有一个"sayHello"函数的副本。为了减少这种内存消耗,我可以像下面这样更改代码:
var Person=(function(){
var sayHello=function(){return 'Hello '+name}
return function(name){
this.name=name
this.sayHello=sayHello
}
})()
这样sayHello()就不会出现多个副本了
我的问题是:
- 第一种代码,除了浪费内存,还有什么好处呢?
- 我们应该用第二种方式编写代码,还是javascript应该避免每个实例一个函数一个副本?
非常感谢。
For the 1st type of code, what's the benefit except wasting more memory?
我唯一一次使用类似的东西是为了快速测试匿名对象。这方面的一个例子是某种 factory 实现:
getWidget = function(){
return {
foo: 'bar',
test: function(){ ... }
}
}
老实说,在我确认我的初始测试后,这将很快被适当的编码约定所取代。
Should we write code in the 2nd way, or javascript should avoid one copy for one function per instance?
我会说不。不要写这样的代码。它不必要地令人费解,而且据我所知似乎不起作用。我建议只在函数原型上创建方法:
var Person = function(name){
this.name = name;
}
Person.prototype.sayHello = function(){
return 'Hello ' + this.name;
}
优点
- 易于阅读
- 易于管理
- this
在调用方法
的上下文中正确限定范围
缺点
- 编码工作的名义增加
- 根据对问题的评论,您无法访问仅限于构造函数的变量
For the 1st type of code, what's the benefit except wasting more memory?
这可用于访问控制(如某些其他语言中的 private
)。
考虑:
var Person=function(name){
this.sayHello = function(){return 'Hello '+name;}
};
name
只能被 sayHello
访问,这是一个不透明的函数。
其他代码可能会替换 this.sayHello
,但无法让此 sayHello
实例使用另一个 name
。
您看到的行为是两件事的结果:
作为第一个 class 对象运行。这意味着函数的处理方式与字符串、数字、数组等相同。
如何在函数中处理局部变量。每次调用函数时都会创建局部变量(通常在堆栈上)。这允许递归调用函数。
这种行为存在于许多具有匿名函数的不同语言中,例如 Go、Perl、Lisp 等
上面的两条规则意味着每次调用函数时都会创建内部函数并将其分配给变量。
这样做有什么好处?
从语言的角度来看,这样做的主要优点是行为的一致性。这意味着函数实际上被视为 first-class 对象,就像数字、字符串等一样。始终如一地对待它意味着尝试使用匿名函数的人不会对这种行为感到惊讶。
人们如何使用此功能?
有时您会发现自己编写了几个看起来相似的不同函数:
function double (x) {return x * 2};
function quadruple (x) {return x * 4};
能够将相似的 "family" 函数分类并以某种方式编写一次,这不是很好吗?
嗯,在像 C 这样的语言中,您可以使用宏系统来基本上剪切和粘贴您键入的文本以生成多个不同的代码。
在具有第一个class函数的语言中,您编写一个函数来生成函数:
function makeMultiplier (factor) {
return function (x) { return x * factor }
}
现在你可以做:
var double = makeMultiplier(2);
var quadruple = makeMultiplier(4);
现在 OBVIOUSLY 要使用 makeMultiplier()
函数 必须 return 两个不同的函数。它不能仅仅修改单个函数来在每次调用时做不同的事情。否则 double()
和 quadruple()
函数将在第二次调用 makeMultiplier()
.
后乘以 4
实施细节
可以创建一个系统,其中内部函数的主体只编译一次,差异由闭包捕获。所以所有函数只占用 RAM 一次,但一个函数的不同版本可能占用多个闭包。这可能是大多数 js 引擎的实现方式,但我真的不知道。如果是这样,那么内部函数 do 每次定义它们时都会占用额外的 RAM 但不会太多(通常是一个堆栈帧 - 所以每个函数定义占用相同的 space 作为函数调用)。
虽然从程序员的角度来看,内部函数必须看起来像每次调用时创建的一样工作,因为这就是您希望它们工作的方式。
javascript介绍说: 当我有如下代码时:
var Person=function(name){
this.name=name;
this.sayHello=function(){return 'Hello '+name;}
}
每当我实例化一个"Person"时,内存中就会有一个"sayHello"函数的副本。为了减少这种内存消耗,我可以像下面这样更改代码:
var Person=(function(){
var sayHello=function(){return 'Hello '+name}
return function(name){
this.name=name
this.sayHello=sayHello
}
})()
这样sayHello()就不会出现多个副本了
我的问题是:
- 第一种代码,除了浪费内存,还有什么好处呢?
- 我们应该用第二种方式编写代码,还是javascript应该避免每个实例一个函数一个副本?
非常感谢。
For the 1st type of code, what's the benefit except wasting more memory?
我唯一一次使用类似的东西是为了快速测试匿名对象。这方面的一个例子是某种 factory 实现:
getWidget = function(){
return {
foo: 'bar',
test: function(){ ... }
}
}
老实说,在我确认我的初始测试后,这将很快被适当的编码约定所取代。
Should we write code in the 2nd way, or javascript should avoid one copy for one function per instance?
我会说不。不要写这样的代码。它不必要地令人费解,而且据我所知似乎不起作用。我建议只在函数原型上创建方法:
var Person = function(name){
this.name = name;
}
Person.prototype.sayHello = function(){
return 'Hello ' + this.name;
}
优点
- 易于阅读
- 易于管理
- this
在调用方法
缺点 - 编码工作的名义增加 - 根据对问题的评论,您无法访问仅限于构造函数的变量
For the 1st type of code, what's the benefit except wasting more memory?
这可用于访问控制(如某些其他语言中的 private
)。
考虑:
var Person=function(name){
this.sayHello = function(){return 'Hello '+name;}
};
name
只能被 sayHello
访问,这是一个不透明的函数。
其他代码可能会替换 this.sayHello
,但无法让此 sayHello
实例使用另一个 name
。
您看到的行为是两件事的结果:
作为第一个 class 对象运行。这意味着函数的处理方式与字符串、数字、数组等相同。
如何在函数中处理局部变量。每次调用函数时都会创建局部变量(通常在堆栈上)。这允许递归调用函数。
这种行为存在于许多具有匿名函数的不同语言中,例如 Go、Perl、Lisp 等
上面的两条规则意味着每次调用函数时都会创建内部函数并将其分配给变量。
这样做有什么好处?
从语言的角度来看,这样做的主要优点是行为的一致性。这意味着函数实际上被视为 first-class 对象,就像数字、字符串等一样。始终如一地对待它意味着尝试使用匿名函数的人不会对这种行为感到惊讶。
人们如何使用此功能?
有时您会发现自己编写了几个看起来相似的不同函数:
function double (x) {return x * 2};
function quadruple (x) {return x * 4};
能够将相似的 "family" 函数分类并以某种方式编写一次,这不是很好吗?
嗯,在像 C 这样的语言中,您可以使用宏系统来基本上剪切和粘贴您键入的文本以生成多个不同的代码。
在具有第一个class函数的语言中,您编写一个函数来生成函数:
function makeMultiplier (factor) {
return function (x) { return x * factor }
}
现在你可以做:
var double = makeMultiplier(2);
var quadruple = makeMultiplier(4);
现在 OBVIOUSLY 要使用 makeMultiplier()
函数 必须 return 两个不同的函数。它不能仅仅修改单个函数来在每次调用时做不同的事情。否则 double()
和 quadruple()
函数将在第二次调用 makeMultiplier()
.
实施细节
可以创建一个系统,其中内部函数的主体只编译一次,差异由闭包捕获。所以所有函数只占用 RAM 一次,但一个函数的不同版本可能占用多个闭包。这可能是大多数 js 引擎的实现方式,但我真的不知道。如果是这样,那么内部函数 do 每次定义它们时都会占用额外的 RAM 但不会太多(通常是一个堆栈帧 - 所以每个函数定义占用相同的 space 作为函数调用)。
虽然从程序员的角度来看,内部函数必须看起来像每次调用时创建的一样工作,因为这就是您希望它们工作的方式。