为什么javascript函数每次调用都有实例? [英] Why javascript function has instance per call?

查看:143
本文介绍了为什么javascript函数每次调用都有实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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()



我的问题是:


  1. 对于第一种类型的代码,有什么好处除了浪费更多的内存吗?

  2. 我们应该用第二种方式编写代码,否则javascript应该避免为每个实例的一个函数使用一个副本?

非常感谢。

解决方案

您目睹的行为是两件事情的结果:


  1. 作为第一类对象。这意味着函数的处理方式与字符串,数字,数组等相同。

  2. 在函数中如何处理局部变量。每次调用函数时都会创建局部变量(通常在堆栈上)。这允许以递归方式调用函数。

这种行为存在于许多具有匿名函数的许多不同语言中,例如Go,Perl ,Lisp等。

上面的两条规则意味着每次调用函数时,都会创建内部函数并将其分配给变量。



这有什么优势?



从语言的角度来看,这样做的主要优点是行为的一致性。这意味着函数被视为一类对象,就像数字,字符串等一样对待它。这意味着尝试使用匿名函数的人不会为这种行为感到惊讶。



人们如何使用此功能?



有时您会发现自己写了几个看起来类似的不同功能:

 函数double(x){return x * 2}; 
函数quadruple(x){return x * 4};

如果能够对类似的功能家族进行分类,这不是很好吗?以某种方式将它们写入一次?



那么,在像C这样的语言中,您可以使用宏系统来基本上剪切并粘贴您输入的文本以生成多个不同的代码。 / p>

在具有first-class-functions的语言中,您可以编写函数来生成函数:

 函数makeMultiplier(factor){
return function(x){return x * factor}
}

现在你可以这样做:

  var double = makeMultiplier(2); 
var quadruple = makeMultiplier(4);

现在显而易见为此工作 makeMultiplier ()函数必须返回两个不同的函数。它不能仅仅修改一个函数来在每次调用时做不同的事情。否则,在第二次调用<$ c $之后, double() quadruple()函数将乘以4 c> makeMultiplier()。






实现细节



可以创建一个系统,内部函数的主体只编译一次,差异由闭包捕获。所以所有函数只占用一次RAM,但不同版本的函数可能占用多个闭包。这可能是大多数js引擎实现它的原因,但我不知道。如果是这样,那么内部函数 do 每次定义时都占用额外的RAM,但不会太多(通常是一个堆栈帧 - 因此每个函数定义占用与函数调用相同的空间)。 从程序员的角度来看,内部函数必须看起来像每次调用时创建的一样,因为这就是你期望它们工作的方式。

p>

The javascript introduction says: When I have code like below:

var Person=function(name){ 
     this.name=name; 
     this.sayHello=function(){return 'Hello '+name;} 
} 

Whenever I instantiate a "Person", there will be a copy of "sayHello" function in the memory. To reduce this memory consumption, I can change the code like below:

var Person=(function(){ 
     var sayHello=function(){return 'Hello '+name} 
     return function(name){ 
         this.name=name 
         this.sayHello=sayHello 
     } 
})() 

In this way, there'll not be multiple copies of sayHello()

My questions are:

  1. For the 1st type of code, what's the benefit except wasting more memory?
  2. Should we write code in the 2nd way, or javascript should avoid one copy for one function per instance?

Thanks a lot.

解决方案

The behavior you are witnessing is the result of two things:

  1. Functions as first-class objects. This means functions are treated the same way as strings, numbers, arrays etc.

  2. How local variables are treated in functions. Local variables are created (typically on the stack) each time the function is called. This allows functions to be called recursively.

This behavior exists in many different languages that have anonymous functions like Go, Perl, Lisp etc.

The two rules above means that each time you call your function the inner function gets created and assigned to the variable.

What's the advantage of this?

The primary advantage of this from the language point of view is consistency of behavior. It means functions are really treated as first-class objects just like numbers, strings etc. Treating it consistently means that people who try to use anonymous functions won't get surprised by the behavior.

How do people use this feature?

Sometimes you find yourself writing several different functions that look similar:

function double (x) {return x * 2};
function quadruple (x) {return x * 4};

Wouldn't it be nice to be able to categorize a "family" of functions that are similar and somehow write them once?

Well, in languages like C you may use a macro system to basically cut-and-paste the text you type to generate several different code.

In languages with first-class-functions you write a function to generate functions:

function makeMultiplier (factor) {
    return function (x) { return x * factor }
}

So now you can do:

var double = makeMultiplier(2);
var quadruple = makeMultiplier(4);

Now OBVIOUSLY for this to work the makeMultiplier() function MUST return two different functions. It cannot just modify a single function to do different things each time it is called. Otherwise both the double() and quadruple() functions will multiply by 4 after the second call to makeMultiplier().


Implementation detail

It is possible to create a system whereby the body of inner functions are compiled only once and the differences are captured by a closure. So all functions only occupy RAM once but different versions of a function may occupy more than one closure. It is possible that this is how it's implemented by most js engines but I don't really know. If so, then inner functions do take up additional RAM each time they're defined but not by much (typically by one stack frame - so each function definition takes up the same space as a function call).

From the programmer's point of view though, inner functions must appear to work as if they're created each call because that's how you'd expect them to work.

这篇关于为什么javascript函数每次调用都有实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆