函数的3种定义方式,函数的参数的理解,函数声明与函数表达式区别

2017-8-24 18:09:48 4,311 views

function类型

每个函数都是Function类型的实例
由于函数是对象,因此函数名实际上也是一个指向函数对象的指针。

函数的3中定义方式

使用函数声明

function sum(num1,num2){
return num1+num2;
}

 

使用函数表达式定义

var sum=function(num1,num2){
return num1+num2;
};

 

使用function构造函数

可以接收任意数量的参数,但最后一个参数始终都被看成是函数体
var sum=new Function("num1","num2","return num1+num2; ");//不推荐,会导致2次解析代码(第一次解析常规es代码,第二次解析传入构造函数中的字符串.从而影响性能);
由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同。也可以说一个函数可能会有多个名字。
function sum(num1,num2){
return num1+num2;
}
alert(sum(10,10));//20
var anotherSum=sum;//使用不带圆括号的函数名是访问函数指针,而并非调用函数,此时anotherSum和sum指向同一个函数。因此anotherSum()也可以被调用并返回结果
alert(anotherSum(10,10));//20
sum=null;
alert(anotherSum(10,10));//20

 

函数声明与函数表达式区别

主要在于解析器,解析器会率先读取函数声明,并使其在执行任何代码之前可用,至于函数表达式.则必须等到解析器执行到它所在的代码行,才会真正被执行
alert(sum(10,10));//20
function sum(num1,num2){
return num1+num2;
}

 

因为解析器通过函数声明提升的过程,将函数声明添加到执行环境中,
alert(sum(10,10));//unexpected identifier 意外标识符错误
var sum=function(num1,num2){
return num1+num2;
};

 

因为函数位于一个初始化语句中,而不是一个函数声明.也就是说在执行到函数所在的语句之前,变量sum中不会保存有对函数的引用;而且由于第一行代码就会导致意外标识符错误,也就执行终止了
除了什么时候通过变量访问函数这一点区别之外,2者的语法其实是等价的。
如果同时使用函数声明和函数表达式
var sum=function sum(){};//会在Safari中报错

函数的参数的理解

es不介意传递进来多少个参数,也不在乎参数是什么数据类型。
即便你定义的函数只接收2个参数,在调用这个函数时也未必一定要传递2个参数,可以传递一个,或者3个甚至不传递参数,而解析器不会有什么怨言。因为es中的参数在内部是用一个数组来表示的吗,函数接收到的始终是这个数组,而不关心有哪些参数。
可以通过arguments对象来访问这个参数数组,从而获取每一个参数.

函数内部属性

在函数内部有2个特殊的对象,arguments和this对象,
arguments是一个类数组对象,主要用来保存函数参数
它有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数。
function factorial(num){
if(num<=1){
return 1;
}else{
return num*factorial(num-1);
}
}
console.log(factorial(5));//120
//用到了递归算法.这个函数的执行与函数名factorial紧紧耦合在了一起。为了消除耦合,可以用arguments.callee
function factorial(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
console.log(factorial(5));//120

 

this对象

this引用的是函数执行的环境对象--或者可以说是this值(当在网页的全局作用域中调用函数时,this对象引用的就是window)
window.color="red";
var o={color:"blue"};
function sayColor(){
alert(this.color);
}
sayColor();//"red";
o.sayColor=sayColor;
o.sayColor();//blue;

 

//当在全局作用域中调用sayColor()时,this引用的是全局对象window,也就是说对this.color的求值会转换成对window.color求值,于是结果就返回了"red",当把这个函数赋给对象o并调用o.sayColor()时,this引用的是对象o,因此对this.color求值会转换成对o.color求值,于是返回了"blue";

caller

:这个函数对象的属性中保存着调用当前函数的函数的引用,如果在全局作用域中调用当前函数,它的值为Null
function outer(){
inner();
}
function inner(){
alert(inner.caller);
}
outer();//会显示outer的源代码.因为outer调用了inner,所以inner.caller就指向了outer(),为了实现更松散的耦合,也可以通过
arguments.callee.caller来访问相同的信息
function outer(){
inner();
}
function inner(){
alert(arguments.callee.caller);
}
outer();

 

当函数在严格模式下运行时,访问arguments.callee会导致错误
转载自http://www.suanliutudousi.com/2017/08/24/%E5%87%BD%E6%95%B0%E7%9A%843%E7%A7%8D%E5%AE%9A%E4%B9%89%E6%96%B9%E5%BC%8F%E5%87%BD%E6%95%B0%E7%9A%84%E5%8F%82%E6%95%B0%E7%9A%84%E7%90%86%E8%A7%A3%E5%87%BD%E6%95%B0%E5%A3%B0%E6%98%8E%E4%B8%8E/
2

分享到微信朋友圈

打开微信,点击底部的“发现”,
使用“扫一扫”即可将网页分享至朋友圈。