函数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。
我在网上和书上都找了相关知识,但好像这个问题太简单了,可以说是一带而过,求解答,谢谢。
在定义函数的时候,都做了哪些工作呢?
There is no silly question! 这是一个好问题啊,ECMA 标准里面有一节专门讲的就是这个问题。
我在网上和书上都找了相关知识
你确定你找对地方了么?这种问题不应该去看 ECMA 标准么?
简单来说,在 JavaScript 中,因为函数是一等对象,定义函数的时候,实际上就是创建了一个对象,就这么简单!不过为了保证这个对象能够调用,它有几个特殊的内部属性/方法:
当调用函数的时候,实际上就是调用该函数对象的
[[Call]]
内部方法;当使用
new
调用函数的时候,实际上就是调用该函数对象的[[Construct]]
内部方法。定义函数时,
{}
之间的东西,不管是什么,哪怕是空的,全部原封不动地保存在[[Code]]
内部属性里;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)。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.