对于面向对象编程的语言来说,对象是很重要的一个概念,而对于函数来说,每个函数实际上都是对象,每个函数都是Function类型的实例,而且与其他引用类型一样具有属性和方法。
函数声明与函数表达式
通常有三种声明函数的方法
- 使用函数声明语法123function sum(num1, num2) {return num1 + num2;}
这也是最常用的方法
- 使用函数表达式定义函数123var sum = function (num1, num2) {return num1 + num2;};
可能会注意到function
关键字后面没有函数名,这是因为使用函数表达式定义函数时,通过变量sum
就可以引用函数
- 使用Function构造函数1var sum = new Function("num1", "num2", "return num1 + num2");
但是非常不推荐这种写法,因为这种语法会导致解析两次代码(第一次解析ECMAScript代码,第二次解析传入构造函数的参数)从而影响性能
关于变量提升
对于1,2两种声明函数的方法有什么不同呢?看下面这个例子
实际上,解析器在执行环境中加载数据时,解析器会率先读取函数声明,并使其在执行任何代码之前可用,而至于函数表达式,则必须等到解析器执行到它所在的代码行才会真正被解释执行。
函数内部属性
在函数内部,有两个特殊的对象:arguments
和this
arguments
是一个类数组对象,包含着传入函数的所有参数,之前在基础算法的时候已经讲过。但是arguments
还有一个名叫callee
属性,该属性是一个指针,指向拥有arguments
对象的函数。具体用法之前写过了,看这里
另一个比较特殊的对象就是this
了,关于this
知乎上@方方老师的这篇文章讲的特别好
函数的属性和方法
因为在ECMAScript中函数是对象,因此函数也有属性和方法。
每个函数包含两个属性:length
和prototype
length
表示函数接受的参数的个数
另一个属性prototype
是保存引用类型所有实例方法的真正所在,比如toString()
和valueOf()
等方法都保存在prototype
名下,prototype
在实现继承时非常重要,下一篇我们再讲。
每个函数都包含两个非继承来的方法:apply()
和call()
apply()
和call()
都是在特定的作用域中调用函数,等于设置函数体内this
的值,他们的区别在于:apply()
接受两个参数:一个是在其中运行函数的作用域,另一个是参数数组,既可以是Array
实例,也可以是arguements
对象。call()
第一个参数和apply()
一样,但是传递参数的时候,必须逐个例举出来。
|
|
既然apply()
和call()
的参数有作用域,那么是用来干什么的呢?看下面的例子:
|
|
是不是this
的值又懵了?如果懵了,就翻上去看方方老师那篇文章。
没错,apply()
和call()
的作用就是扩充函数的作用域
大概就是这么多了,书上这一章的内容我反复看了好几遍才理解,所以学习哪有什么捷径,无他,唯手熟尔
那么,聪明的你,看完之后懂了没有?
下一篇准备讲原型