函数的本质
函数怎么调用
如果是数据,就是直接用的。比如 n = 1,要用就直接写上 n 就可以了。而函数要用的话叫做 调用,英文 call 或者 invoke。那函数是怎么调用的了?比如
function f(x,y) {return x+y} |
函数 f 怎么调用了?
首先我们看,函数到底是什么?
函数是一段可以反复调用的代码块
比如,我们求三角形的面积,我们知道它的宽为 100、高为 200。三角形面积公式为 S = ah/2。所以结果为 100 x 200 / 2 = 10000。JavaScript 代码写下来:
width = 100 |
那上面的 var area = width * height / 2
以及返回 area
就是求三角形面积的两句话,那我们可以把这两句话写成一个函数,然后取一个名字。比如说:
function 求三角形面积(w,h) { |
求三角形面积 这个函数就可以反复调用。
函数在内存中是怎么存的?
函数在内存里面是存的函数 toString 值。实际上是一个字符串。
function f(x,y){return x+y}
改用更明确的形式 var f = new Function('x', 'y', 'return x+y')
在栈中存入 f,值为 ADDR 77,然后在堆中有一个 ADDR 77 的值,它里面对应存了函数的参数,比如 params:['x', 'y']
,然后还有函数体 fbody:'return x+y'
,然后就是函数的共有属性 __proto__
。而 __proto__
里面有个方法叫 call,call 调用 fbody
。
这个调用的过程:
var f = {} |
函数是一个对象,因为函数的调用过程,其实就是 eval 它的函数体的过程。
eval 的参数是字符串,eval 执行它的参数。
所以可以总结为:可以执行代码的对象叫做函数。
硬核玩家函数调用
function f(x,y) {return x+y} |
知识体系回顾
JavaScript 有 7 种数据类型:number,string,boolean,null,undefined,symbol,object
最复杂的就是 object 它是复杂对象,它能包含其他数据类型。
比如一个普通对象 {name: ‘frank’},它有个 toString 方法,继承自它的 __proto__
,__proto__
指向 Object.prototype。还有一个 Array.prototype 的原型,比如我们有个数组 [1,2,3],它有个__proto__
,它是指向 Array.prototype,它有 push,pop 等方法。然后有个 Function.prototype 的原型,比如我们有个函数 var f = function(){}
,它有个__proto__
,它指向 Function.prototype,它里面有 bind、call、apply 方法。
其他
var a = 1,2 // 报错 |