学习内容来自:《JavaScript高级程序设计(第三版)》segmentfault
正文:咱们知道,在js中,函数其实是一个对象,每一个函数都是Function类型的实例,而且都与其余引用类型同样具备属性和方法。所以,函数名其实是指向函数对象的指针,不与某个函数绑定。在常见的两种定义方式(见下文)以外,还有一种定义的方式能更直观的体现出这个概念:闭包
var sum = new Function("num1", "num2", "return num1 + num2"); //不推荐
Function的构造函数能够接收任意数量的参数,但最后一个参数始终被看作函数体。这种方式有个缺点是,会致使解析两次代码,第一次是基础的ES代码解析,第二次是解析传入构造函数中的字符串,这样会致使性能的降低,在此写出是帮助理解js中函数实际上是对象这个概念。框架
(一)js函数没有重载的概念函数
说到重载的概念,咱们来类比Java中的重载是怎么实现的:在Java中,方法是经过方法签名来惟一标识一个方法。方法签名包括:方法名、参数数量、参数顺序和参数类型这几个要素。所以两个方法的方法名相同,而其余签名要素不一样,编译器就会认为是两个不一样方法,从而能够存在同名的不一样方法,以实现重载的概念。(引用:怎么深刻理解js中为何没有重载呢--segmentfault 中manxisuo的回答)。性能
而上面咱们说过,js中的函数名其实是指向函数对象的指针,所以函数名能够说是一个函数的惟一标识,跟参数列表并无关系,所以并不会出现同名的两个函数(由于一个指针同时只能指向一个对象)从而不存在重载的概念。 举个栗子:学习
function sum(num1, num2){ return num1 + num2; } function sum(num1, num2, num3){ return num1 + num2 + num3; }
上面这种能够换一种写法,会更直观一些:spa
var sum = function(num1, num2){ return num1 + num2; } sum = function(num1, num2, num3){ return num1 + num2 + num3; }
这样就很明显能够看出,上面一行将sum指向function(num1,num2),而接下来又将sum指向function(num1, num2, num3),从而形成第二次的指向覆盖了第一次的,所以更明显的看出js中并无重载的概念。设计
(二)函数声明和函数表达式的区别指针
咱们知道,经常使用的定义函数方法有两个:函数声明和函数表达式。code
函数声明,能够说是最多见的定义方法,以下例:
function sum(num1, num2){ return num1 + num2; }
函数表达式,这种定义方式在闭包及一些框架中使用较多,例如angular中常见的$scope.doSomething = function(){...}:
sum = function(num1, num2){ return num1 + num2; };
上述两种定义方法几乎是相同的,但有一点小区别,请看下面这个例子:
//函数声明 alert(sum(100, 100)); function sum(num1, num2){ return num1 + num2; }
//函数表达式 alert(sum(100, 100)); var sum = function(num1, num2){ return num1 + num2; };
这两段代码看起来差异不大,只是函数定义的方式不一样而已。但事实是,第一段能够正常运行而第二段则会报错。这是由于,在代码开始执行以前,解析器就已经经过一个名为函数声明提高的过程,读取并将函数声明添加到执行环境中。简单来讲,解析器会先将函数声明放在源代码树的顶部。而下面那段代码,函数位于一个初始化语句中(并不会将其提高到顶部),简单来讲,在执行到这个赋值语句以前,sum并未指向任何一个函数,所以在以前调用函数则会报错。
--待续--