函数
什么是函数:具有特定功能的模块。在JS中函数也是一种特殊的对象,具有属性和方法。
函数的创建方式:函数声明方式、函数表达式方式、构造方法方式
函数声明创建函数
function 函数名(形参列表) {
函数体;
}
注意
function关键字不可以省略
函数名是一种特殊的变量,保存的是函数对象在内存中的地址。函数名的命名规则必须符合标识符的命名规则
定义函数时的参数称为形参,形参是用来接收函数被调用时传过来的数据的变量。形参在定义时不加var ,形参的个数可以是一个,也可以是多个,如果是多个,用逗号分隔。形参只有函数被调用时才分配存储空间,函数执行完毕该空间释放
大括号中的内容是实现函数功能的语句,语句可以是0条,也可以是多条
大括号后面不加分号
函数表达式创建函数
//格式
var 变量名 = function(形参列表){函数体};
//调用
变量名(实参列表);
注意
var关键字可以省略,可以不省,建议不省略
变量名保存的是函数在内存中的地址,必须符合标识符的命名规则
等号右面的函数为一个匿名函数,定义要求和函数声明时的要求相同
大括号后面一定要加分号
函数声明方式创建函数和函数表达式方式创建函数的区别
函数声明方式有函数名,但是函数表达式方式创建的函数没有函数名,只有对象名
函数声明方式创建的函数在预编译时会有函数提升,而函数表达式方式创建的函数在预编译时不会有函数提升(简单理解:函数声明方式创建的函数可以在定义该函数前面调用,但是函数表达式方式创建的函数不可以再定义之前调用)
<script type="text/javascript">
fn(); //函数提升,js预编译时会将声明创建的函数自动提升到最前面,所以此时可以调用成功
function fn() { console.log("hello world"); }
</script>
函数声明方式创建的函数,全局变量
函数构造创建函数
//格式
var 函数对象名 = new Function('参数1', '参数2', '函数体');
//创建无参构造函数
var fn = new Function('console.log("hello world");');
//创建带参构造函数
var fn2 = new Function('str','console.log(str);');
匿名自执行函数
先写两个()()
第一个()写function(形参列表){函数体}
第二个()写实参列表
最后补上;
//带参
(function(形参列表){函数体})(实参列表);
(function(str){console.log(str);})("hello world");
//有返回值
var 变量名 = (function(形参列表){函数体})(实参列表);
var res = (function(a,b){return a+b;})(1,2);
特殊格式
(function(形参列表){函数体}(实参列表));
~function(形参列表){函数体}(实参列表);
!function(形参列表){函数体}(实参列表);
+function(形参列表){函数体}(实参列表);
–function(形参列表){函数体}(实参列表);
(function(形参列表){函数体}).call(借用者,实参列表);
(function(形参列表){函数体}).apply(借用者,[实参列表]);
为什么要使用匿名自执行函数
JS中没有块级作用域的概念,可以利用匿名自执行函数模拟块级作用域
函数对象中的属性
arguments属性:用来管理实参的对象,它对数据的存储形式类似于数组,但是不是数组,我们称为伪数组。它包含的属性和方法有
length属性:获取实参的个数
callee属性:该属性保存了对arguments所在函数的地址,常用于递归函数中
//取实参
<script type="text/javascript">
function fn(num1, num2) {
console.log(arguments[0]);
console.log(arguments[1]);
}
fn(1, 2);
</script>
//5的阶乘
<script type="text/javascript">
var res = (function(n) {
if (n == 1) {
return 1;
} else {
return n * arguments.callee(n - 1);
}
})(5);
</script>
this属性:代表调用该函数的那个对象,如果是构造函数,那么它代表通过该构造函数创建出来的实例
prototype属性:该属性指向原型对象
length属性:获取形参的个数
方法重载处理
如果两个函数的名称相同,但是参数的个数或者类型不相同,那么这两个函数互为重载函数。
JS中函数没有重载,如果出现两个函数名相同但是参数不同的情况,后面的方法会替换前面的方法。
<script type="text/javascript">
function fn(num1) {
console.log(arguments[0]);
}
function fn(num1, num2) {
console.log(arguments[0]);
console.log(arguments[1]);
}
fn(1); //运行结果1 undefined,因为后面的fn方法替换了前面的fn方法
</script>
值传递和引用传递
值传递:所谓值传递就是形参接收到的数据为非引用类型的地址,而是具体内容
引用传递:所谓引用传递就是形参接收到的数据为引用类型的地址值
<script type="text/javascript">
var arr = [10, 20, 30, 40];
//值传递
function fn1(num1, num2) {
temp = num1;
num1 = num2;
num2 = temp;
}
fn1(arr[0], arr[1]);
console.log(arr);
//引用传递
function fn2(obj) {
temp = obj[0];
obj[0] = obj[1];
obj[1] = temp;
}
fn2(arr);
console.log(arr);
</script>
嵌套函数
嵌套函数:两个函数间属于包含和被包含的关系时,那么被包含的函数就是一个嵌套函数。内部函数的调用工作默认在外部函数内部。内部函数有权使用外部函数中定义的所有变量。但是外部函数无法使用内部函数中定义的变量
递归函数
递归函数:函数内部调用自己的一种函数。递归函数在使用时一定要出口,否则造成死循环
回调函数
回调函数:所谓回调函数就是作为另外一个函数的参数的函数被称为回调函数,当满足一定条件或达到某种状态时该回调函数被执行。使用回调函数的场景:sort方法、setInterval方法、setTimeout方法、AddEventListener方法,回调的作用是使函数的功能更为灵活