javascript - 如何理解 JS 函数在定义的时候不执行?
怪我咯
怪我咯 2017-04-10 15:22:30
0
6
302

函数1:一个函数声明:

function ff(a){
    alert(a);
    }

函数2:一个函数表达式:

var f=function(){ return (1+2);}

函数只在调用时候执行花括号内的语句,那么在定义函数的时候,都做了哪些工作呢?

比如函数2,var f=function(){ return (1+2);} 是原封不动的把{}花括号内的代码赋值给一个变量吗?
还是说,会计算一下1+2==》var f=function(){ return (3);} ,待调用时返回3。

我在网上和书上都找了相关知识,但好像这个问题太简单了,可以说是一带而过,求解答,谢谢。

怪我咯
怪我咯

走同样的路,发现不同的人生

membalas semua(6)
大家讲道理

在定义函数的时候,都做了哪些工作呢?
There is no silly question! 这是一个好问题啊,ECMA 标准里面有一节专门讲的就是这个问题。

我在网上和书上都找了相关知识
你确定你找对地方了么?这种问题不应该去看 ECMA 标准么?

简单来说,在 JavaScript 中,因为函数是一等对象,定义函数的时候,实际上就是创建了一个对象,就这么简单!不过为了保证这个对象能够调用,它有几个特殊的内部属性/方法:

  • [Call]
  • [[Construct]]
  • [[Scope]]
  • [[Code]]
  • [[FormalParameters]]

当调用函数的时候,实际上就是调用该函数对象的[[Call]]内部方法;
当使用 new 调用函数的时候,实际上就是调用该函数对象的 [[Construct]] 内部方法。

定义函数时,{} 之间的东西,不管是什么,哪怕是空的,全部原封不动地保存在 [[Code]] 内部属性里;

13.2 Creating Function Objects
Given an optional parameter list specified by FormalParameterList, a body specified by FunctionBody, a Lexical Environment specified by Scope, and a Boolean flag Strict, a Function object is constructed as follows:

Create a new native ECMAScript object and let F be that object.
Set all the internal methods, except for [[Get]], of F as described in 8.12.
Set the [[Class]] internal property of F to "Function".
Set the [[Prototype]] internal property of F to the standard built-in Function prototype object as specified in 15.3.3.1.
Set the [[Get]] internal property of F as described in 15.3.5.4.
Set the [[Call]] internal property of F as described in 13.2.1.
Set the [[Construct]] internal property of F as described in 13.2.2.
Set the [[HasInstance]] internal property of F as described in 15.3.5.3.
Set the [[Scope]] internal property of F to the value of Scope.
Let names be a List containing, in left to right textual order, the Strings corresponding to the identifiers of FormalParameterList. If no parameters are specified, let names be the empty list.
Set the [[FormalParameters]] internal property of F to names.
Set the [[Code]] internal property of F to FunctionBody.
Set the [[Extensible]] internal property of F to true.
Let len be the number of formal parameters specified in FormalParameterList. If no parameters are specified, let len be 0.
Call the [[DefineOwnProperty]] internal method of F with arguments "length", Property Descriptor {[[Value]]: len, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}, and false.
Let proto be the result of creating a new object as would be constructed by the expression new Object()where Object is the standard built-in constructor with that name.
Call the [[DefineOwnProperty]] internal method of proto with arguments "constructor", Property Descriptor {[[Value]]: F, { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}, and false.
Call the [[DefineOwnProperty]] internal method of F with arguments "prototype", Property Descriptor {[[Value]]: proto, { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}, and false.
If Strict is true, then
Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
Call the [[DefineOwnProperty]] internal method of F with arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, and false.
Call the [[DefineOwnProperty]] internal method of F with arguments "arguments", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false}, and false.
Return F.
NOTE A prototype property is automatically created for every function, to allow for the possibility that the function will be used as a constructor.

调用函数时,Let result be the result of evaluating the FunctionBody that is the value of F's [[Code]] internal property.,才会对 [[Code]] 属性求值 (evaluate)。

13.2.1 [[Call]]

When the [[Call]] internal method for a Function object F is called with a this value and a list of arguments, the following steps are taken:

Let funcCtx be the result of establishing a new execution context for function code using the value of F's [[FormalParameters]] internal property, the passed arguments List args, and the this value as described in 10.4.3.
Let result be the result of evaluating the FunctionBody that is the value of F's [[Code]] internal property. If F does not have a [[Code]] internal property or if its value is an empty FunctionBody, then result is (normal, undefined, empty).
Exit the execution context funcCtx, restoring the previous execution context.
If result.type is throw then throw result.value.
If result.type is return then return result.value.
Otherwise result.type must be normal. Return undefined.

刘奇

最近看了下《深入理解计算机系统》这本书,小小解答一下

提问者能提出这样的问题,我想您应该具有javascript的基本知识,如解析阶段和执行阶段变量提升等(好像跟我回答的没啥关系...)

直入主题吧

在计算机系统里,整个程序是分部分存储的,大约有这些部分:

  1. 只读的代码和数据,从文件本身加载进来的,固定大小的
  2. 读/写数据,从文件加载经来的,存放变量为原始类型的值,固定大小
  3. 存放引用变量实际指向值的地方,动态扩展的
  4. 用户栈,运行时创建的,用于函数调用啊,事件等等,动态扩展的
  5. CPU里正在执行的代码,包括当前指令和正执行的数据

程序的存储部分大致这样,再讲讲关键点:

  • 在javascript程序运行的过程中,变量本身在程序运行结束之前是不会被销毁的(即内存不会被回收),它们始终存于读/写数据区。被销毁的只是引用数据,这些引用数据是存于运行时堆区的,引用这些数据的变量的实际值是内存地址。
  • 读/写数据区的大小 + 只读的代码和数据区的大小,在加载至内存时(即解析完成后代码的大小)是固定大小不变的。

在加载javascript代码到计算机时,首先,代码本身会首先被解析,包括代码校验二进制翻译变量提升等等,接着会将解析后的代码加载至只读的代码和数据内存区,最后就开始等待执行了。

所以:

javascriptvar f = function () {
  return (1+2);
}

这段代码在解析完成后并加载至内存时,function的执行逻辑会存于只读的代码和数据区,变量f会存于读/写数据区,在定义的时候(1+2)的值不会计算,只有在执行时才会计算。

好像还是没解释清楚,望提问者指出,继续修正!

小白之手,大神勿喷,如有错误,望请更正!

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!