函数的定义: 函数即对象,函数名为指针变量
a. 声明式函数
function demo(a){
console.log(a)
}
b. 函数表达式、命名函数表达式
var fun = function(){ // 函数表达式,俗称匿名函数
return true;
}
var funny = function fun(){ // 命名函数表达式 fun只能在函数体类使用
return true;
}
声明式函数与函数表达式的区别在于前者属于顶级作用域范围(function declaration hositing),而后者是在解释执行时创建的。
函数的参数传递
ECMAScript 中的所有参数传递的都是值,对象传递的是地址,但是原始引用保持不变
ECMAScript函数不介意传递进来多少个参数,也不在乎传进来的参数的数据类型,如果传递的参数个数少于形参,则没有传入实际值的形式参数为undefined, 如果传递的参数个数多余形式参数,则多的自动忽略。
函数的参数可以是函数
ES5中函数的形式参数不能有默认值,但ES6中形式参数可以有默认值
同名参数
在非严格模式下,函数中可以出现同名的形式参数,且只能访问最后出现的该名称的参数,在严格模式下将出错
function demo(x,x,x){
console.log(x); // 4
}
function demo(x,x,x){
"use strict";
console.log(x); // 出错,不能有重复的参数名称
}
形式参数只是提供便利,但不是必须的。
函数的返回值
函数的返回值可以是任意类型,可以是基本类型、对象(函数)。使用return即可。
函数的重名
函数没有重载,后定义的函数会覆盖之前定义的同名函数。因为在js中函数是对象,函数名为指针,所以当声明两个名称一样的函数时,只是改变了函数名的指向,如下
function foo(x,y){
console.log(typeof arguments);
console.log(Object.prototype.toString.call(arguments));
console.log(arguments);
}
var foo = function(x,y){
console.log(x+y);
}
foo(1,2);
函数内部属性对象
1. arguments
arguments 对象是一个类数组对象,包含着传入函数的所有参数。原型为:
callee属性是一个指针,指向拥有这个arguments对象的函数。callee在递归函数中有很大的用处,如下:
var factorial = function(num){
if(num<=1){
return 1;
}else{
return num*factorial(num-1);
}
}
var ff = factorial;
factorial = null;
console.log(ff(2)); // 出错,因为没有找到factorial指向的函数了
var factorial = function(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
var ff = factorial;
factorial = null;
console.log(ff(2)); // 正确
callee 在严格模式下抛出TypeError错误,这是,可以使用命名函数表达式,来实现递归函数,如下:
"use strict";
var factorial = function fn(num){
if(num<=1){
return 1;
}else{
return num*fn(num-1);
}
}
arguments与形式参数的关系
arguments对象中存储了传入函数的实际参数,非严格模式下如果形式参数和实际参数都存在的情况下,则值是同步的,否则不同步;严格模式下彼此独立。形式参数与arguments的存储是不重叠的,属于独立的命名空间,也就是说无论形式参数有没有,arguments对象始终存在。
var factorial = function(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
var ff = factorial;
factorial = null;
console.log(ff(2));
function ff(x,y){
console.log(arguments.length); // 显示arguments的长度
x = 100;
console.log(arguments[0]); // 显示第一个实际参数的值
arguments[0] = 30000;
console.log(x);
console.log(y);
y = 200;
console.log(arguments[1]); // 显示第二个实际参数的值
}
console.log(ff(10));
这段代码运行的结果为10的阶乘,因为javascript hositing,ff声明被提升,只有去掉var ff=factorial才可以执行下面的ff函数。
arguments 与 数组的转换
arguments只是类似数组,但不是数组,因此不具备数据的一些方法,那么如何转换成数组呢,看一下代码
可以使用Array.prototype.slice.call()充当数组来操作
function list(type){
var result = "<" + type + "l><li>";
var args = Array.prototype.slice.call(arguments, 1);
result += args.join("</li><li>");
result += "</li></" + type + "l>"; // end list
return result;
}
demo('u','a','b','c');
// <ul><li>a</li><li>b</li><li>c</li></ul>
2. this
this引用的是函数据以执行的环境对象,在全局作用域中调用函数时,this对象的引用是window。
js中this是动态绑定的,或称为运行时绑定
3. length
length表示函数希望接收的命名参数的个数。 牢记在js中函数是对象。
function demo(x,y){
return x+y;
}
console.log(demo.length); //2
4. prototype
原型
function ff(x,y){
console.log(arguments.length); // 显示arguments的长度 2
x = 100;
console.log(arguments[0]); // 显示第一个实际参数的值 100
arguments[0] = 30000;
console.log(x); 30000
console.log(y); undefined
y = 200;
console.log(arguments[1]); // 显示第二个实际参数的值 undefined
}
console.log(ff(10));