一、理解函数的参数
JS中的函数对于传递进来的参数很宽容,假设你定义的某个函数需要传递一个参数,但是你传递的时候却传递了两个,或者是没传,即使这样,解析器也不会报错。
之所以JS中的函数这么宽容,是因为函数在定义成功后,里面就生成了自动生成了一个对象:arguments。这个对象他长得有点像数组,只是像而已哦,他可以通过方括号语法访问里面的每一个元素,并用length属性判断里面到底传了几个元素。
arguments的意义在于他可以模仿重载。重(zhong)载的意思就是一个函数,传递不同的参数,可以执行不同的方法。而JS是没有重载的。
二、函数对象
函数实际上是对象,每个函数都是Function类型的实例。既然函数式对象,那么函数名实际上就是一个指向函数对象的指针,不会与某个函数绑定,一句话概括:“函数是对象,函数名是指针”。也正因此,一个函数,可以有多个不同的函数名。
例如:
function sum(num1,num2){ return(num1+num2); } var add=sum; console.log(add(19,2),typeof add);//21,function
一个函数可以有多个函数名,但是一个指针却不能指向多个函数,这也就是为什么JS没有重载的原因了。
三、函数的内部属性this
this引用的函数执行环境的对象。
var color="red"; var o={ color:"blue" } function sayColor(){ console.log(this.color); } sayColor();//undefined,这个this指向的是window o.sayColor=sayColor;//必须让这个对象绑定该方法 o.sayColor();//blue
函数的名字只是一个包含指针的变量罢了。即使在不同的环境中执行,全局的sayColor()函数与o.sayColor()函数指向的仍然是同一个函数。
函数的方法:
每个函数都包括两个非继承而来的方法:apply()和call()。这两个方法的用途是在特定的作用域中调用函数,就相当于设置函数体内this的值。
apply()接受两个参数,一个是作用域,一个是数组。前者是在其中运行函数的作用域,后者是参数数组。
后者这个数组,可以是Array实例,也可以是arguments对象。
function sum(num1,num2){ console.log(num1+num2); } function callSum(num1,num2){ return sum.apply(this,arguments); } callSum(1,5,3)//6
call()接受两个参数,第一个是this,后面是其他传递进来的参数。在使用call方法的时候,传递给函数的参数必须逐一列举
他们最主要的作用是扩充作用域。
global.a="red"; function sayA(){ console.log(this.a); } sayA();//red
ES5还定义了一个bind()方法,这个方法会创建一个函数的实例,this值会被绑定给传到bind()函数的值。
this的指向是谁调用,就指向谁。对象里面的函数,要想拿出来使用,就必须要重新定义。
堆:先进先出。字符串、数字
栈:先进后出。数组、对象。
函数式对象,函数名是指针。