在上一篇 JavaScript的三种函数定义方式, 我们提到在 JavaScript 语言里, 函数也是对象, 函数既然是对象就一定有对应的属性和方法, 本篇来讲讲函数的属性和方法。
函数的内部属性
在函数内部有两个特殊的属性: arguments 和 this
1)arguments对象
Javascript并没有重载函数的功能, 但是Arguments对象能够模拟重载。arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。arguments对象不是一个 Array。它类似于Array,但除了长度之外没有任何Array属性。
它引用着函数的实参,可以用数组下标的方式”[]”引用arguments的元素。arguments.length为函数实参个数,arguments.callee引用函数自身。1
2
3
4
5
6person('heeloo', 'word', 'up8', 'Felix Cao');
function person() {
for(var i=0; i<arguments.length; i++) {
console.log('parameter ' + i +': ', arguments[i]);
}
}
阶乘函数(Factorial)1
2
3
4
5
6
7function factorial (num){
if(num <= 1){
return 1;
} else{
return num * factorial(num-1);
}
}
定义阶乘函数一般都会用到递归算法,如上面代码所示,在有函数名字,并且函数名字以后也不会改变的情况下,这种定义是没有问题的,但是这个函数的执行与函数名factorial紧紧的耦合在一起,为了消除这种紧密耦合现象,可以使用arguments.callee1
2
3
4
5
6
7function factorial (num){
if(num <= 1){
return 1;
} else{
return num * arguments.callee(num-1);;
}
}
重写后的factorial()函数的函数体内,没有再引用函数名factorial。这样即使改变函数名字,都可以保证正常完成递归调用.
2) this, 请移步JavaScript中的this绑定/指向
函数的属性
1). length属性
在函数内部属性部分我们讲到arguments对象的length属性表示实参个数,而函数的length属性则表示形参个数1
2
3
4
5function person(name, age) {
console.log('实参个数:', arguments.length);
console.log('形参个数:', person.length);
}
person('up8', 2, '127.0.0.1');
2). name属性
函数定义了一个非标准的name属性,通过这个属性可以访问到给定函数指定的名字,这个属性的值永远等于跟在function关键字后面的标识符,匿名函数的name属性为空1
2
3
4
5
6
7
8//IE11-浏览器无效,均输出undefined
//chrome在处理匿名函数的name属性时有问题,会显示函数表达式的名字
function fn(){};
console.log(fn.name);//'fn'
var fn = function(){};
console.log(fn.name);//'',在chrome浏览器中会显示'fn'
var fn = function abc(){};
console.log(fn.name);//'abc'
[注意]name属性早就被浏览器广泛支持,但是直到ES6才将其写入了标准,ES6对这个属性的行为做出了一些修改。如果将一个匿名函数赋值给一个变量,ES5的name属性,会返回空字符串,而ES6的name属性会返回实际的函数名1
2var func1 = function () {};
func1.name //ES5: ""
如果将一个具名函数赋值给一个变量,则ES5和ES6的name属性都返回这个具名函数原本的名字1
2
3var bar = function baz() {};
bar.name //ES5: "baz"
bar.name //ES6: "baz"
Function构造函数返回的函数实例,name属性的值为“anonymous”1
(new Function).name // "anonymous"
bind返回的函数,name属性值会加上“bound ”前缀1
2
3function foo() {};
foo.bind({}).name // "bound foo"
(function(){}).bind({}).name // "bound "
3). prototype属性
每一个函数都有一个prototype属性,这个属性指向一个对象的引用,这个对象称做原型对象(prototype object)。每一个函数都包含不同的原型对象。将函数用做构造函数时,新创建的对象会从原型对象上继承属性. 关于prototype属性请移步 JavaScript原型、原型对象、隐式原型
函数的方法
每个函数都有call(),apply(), bind()三个方法,他们来源于Function.prototype.call(),Function.prototype.apply(), Function.prototype.bind(), 上文提到,在JavaScript 语言里, 函数也是对象,每个函数都是 Function 类的实例,而call、apply和bind是Function类自带的三个方法。 想了解更多请移步JavaScript函数的call/apply/bind方法
toStrint方法
函数的toString方法返回一个字符串,内容是函数的源码。1
2
3
4function add(x,y) {
return x+y;
}
add.toString()