函数声明与函数表达式
函数声明通常是用函数声明语法定义的,如下例子所示。
function sum () {
//...
}
函数表达式的定义函数的例子,如下所示。
var sum = function () {
//...
};
以上代码定义了一个变量sum并将其初始化为一个函数。
还可以使用Function构造函数定义函数,不推荐使用
//接收任意数量参数,但最后一个参数被看做函数体,前面的参数为新函数的参数
var sum = new Function(arg1, arg2 );
函数声明会提升到顶部。函数表达式不提升,但函数表达式定义的变量会提升,初始化时变量sum不会保存对函数的引用。
//output: 2
sum(1, 1);
function sum (num1, num2) { console.log(num1 + num2); } //console.log(sum);//undefined
//sum(1, 1);//TypeError
// var sum = function (num1, num2) {
// console.log(num1 + num2);
// }
函数内部属性
在函数内部有两个特殊的对象arguments
和this
callee
,是arguments的一个属性,是一个指针,指向拥有指向arguments对象的函数。
//递归函数
function factorial (num) {
if (num <= 1) {
return 1;
} else {
//callee指向函数factorial()
return num * arguments.callee(num - 1);
}
}
this
,this引用的是函数执行的环境对象。
caller
函数的caller属性,该属性保存着调用当前函数的函的引用,如果在全局作用域中调用,它的值为null。
"use strict";
function outer() {
inner();
}
function inner() {
// inner.caller = "a";//严格模式下不能给caller属性赋值
console.log(inner.caller);
//arguments.callee.caller也指向拥有指向arguments对象的函数
// console.log(arguments.callee.caller);//严格模式下访问导致错误
}
outer();
/* 输出outer()函数的源代码 ƒ outer () { inner(); } */
函数的属性和方法、
每个函数都包含两个属性length
和prototype
length
表示函数希望接受的命名参数个数。
function sum (arg1, arg2, arg3) {
//...
}
//3
console.log(sum.length);
prototype
,不可枚举
引用类型的所有实例方法保存在prototype属性,通过实例访问。
每个函数包含两个非继承来的方法apply()
和call()
这两个方法都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
apply()
接受两个参数,一个是在其中运行的函数的作用域( 非严格模式的全局作用域下,传入this值,就是window对象。严格模式的全局作用域下,this不会转型为window, 除非明确将某个对象调用apply(),call(),否则this是undefined), 另一个是参数数组(可以是Array实例,也可以是arguments对象)。
var color = 'red';
function sayColor () {
console.log(this.color);
}
var blue = {
color: 'blue'
};
//red
sayColor();
//blue
sayColor.apply(blue);
call()
与apply()作用相同,区别仅在于接收参数的方式不同。call()必须明确地传入每一个参数。
使用apply(),call()来扩充作用域,好处,不用给对象额外添加方法。