函数它只定义一次,但可能被执行或调用屡次 。
Function类型是JavaScript提供的引用类型之一,经过Function类型建立Function对象。
在JavaScript中,函数也是以对象的形式存在的。每一个函数都是一个Function对象。函数名,本质就是一个变量名,是指向某个Function对象的引用。数组
// 1.函数声明方式 function fun(){ console.log('this is function'); } // 2.字面量方式 var fn = function(){ console.log('this is function too'); } // 判断函数是否为Function类型的 console.log(fun instanceof Function);// true console.log(fn instanceof Function);// true // JavaScript中全部的函数都是Function类型的对象 /* 3.建立Function类型的对象 -> 是一个函数 var 函数名 = new Function(参数,函数体); * 因为函数的参数和函数体都是以字符串形式传递给Function的 */ var f = new Function('a','console.log(a)'); f(100);// 以函数方式进行调用
在JavaScript中,函数除了能够经过函数定义语句或字面量表达式两种方式定义以外,还能够经过Function类型进行定义。(注意:经过Function类型定义函数的效率远不如经过函数定义语句或字面量表达式两种方式定义。目前,定义函数具备三种方式,这三种方式之间存在必定的差异。)闭包
// 1.Object与Function都是自身的类型 console.log(Object instanceof Object);// true console.log(Function instanceof Function);// true // 2.Object自身是构造函数,而构造函数也是函数,是函数都是Function类型 console.log(Object instanceof Function);// true // 3.Function是引用类型,用于建立对象,是对象都是Object类型 console.log(Function instanceof Object);// true
// 变量的声明提早 console.log(v);// undefined var v = 100; // 若是使用函数声明方式定义函数时 -> 函数的声明提早 fun(); function fun(){ console.log('this is function'); }
Function的apply()方法用于调用一个函数,而且接受指定的this值,以及一个数组做为参数。
语法结构:
1.thisArg参数:可选项,在func函数运行时使用this值。
2.argsArray参数:可选项,一个数组或者类数组对象,其中你那个的数组元素将做为单独的参数传给func函数。也可使用argments对象做为参数
3.返回值:调用该函数的返回结果。app
// 定义函数 function fun(value){ console.log('this is ' + value); } // 函数的调用方式 fun('function');// 语法结构:函数名称() apply(thisArg,argArray)方法 -> 用于调用一个指定函数 参数 thisArg - this argArray - 数组,做为参数(实参)的列表 fun.apply(null, ['function']);
Function的call()方法用于调用一个函数,而且接收指定的this值做为参数,以及参数列表。
语法结构:
1.thisArg参数:在func函数运行时使用的this值。
2.arg1,arg2,...参数:指定的参数列表。
3.返回值:调用该函数的返回结果。
apply()与call()很是类似,不一样之处在于提供参数的方式。函数
Function的bind()方法用于建立一个新的函数(称之为绑定函数),而且接收指定的this值做为参数,以及参数列表。布局
// 定义函数 function fun(value){ console.log('this is ' + value); } /* bind(thisArg, arg1, arg2, ...)方法 * 做用 - 用于建立一个新函数(称为绑定函数) * 参数 * thisArg - this arg1, arg2, ... - 表示参数列表 * 返回值 - 返回新的函数 */ // var f = fun.bind();// 相对于从指定函数复制一份出来 // console.log(f); // f(); fun('周芷若');// this is 周芷若 var f = fun.bind(null, '张无忌'); f();// this is 张无忌
在其余开发语言中,函数具备一种特性,叫作重载。所谓的重载,就是定义多个同名的函数,但每个函数接收的参数的个数不一样,程序会根据调用是传递的实参个数进行判断,具体调用的是哪一个函数。this
// 定义函数 function fun(value){ console.log('this is ' + value); } bind(thisArg, arg1, arg2, ...)方法 做用 - 用于建立一个新函数(称为绑定函数) 参数 thisArg - this arg1, arg2, ... - 表示参数列表 返回值 - 返回新的函数 var f = fun.bind();// 相对于从指定函数复制一份出来 console.log(f); f(); fun('周芷若');// this is 周芷若 var f = fun.bind(null, '张无忌'); f();// this is 张无忌
但在JavaScript中函数时没有重载现象的。也就是说,若是同时定义多个同名函数,只有最后一个定义的函数时有效的。
不过,JavaScript提供的arguments对象,该对象能够模拟函数重载的现象。arguments对象是函数内部的本地变量;arguments已经再也不是函数的属性了。
arguments对象能够获取函数的全部参数,但arguments对象并非一个数组,而是一个类数组对象(没有数组特有的方法)。code
在一个函数体内,若是想调用自身函数的话,有两种方式;
1.经过使用自身函数实现
2.经过使用arguments对象的callee属性实现。
调用自身的函数被称之为递归函数。在某种意义上,递归近似于循环。二者都重复执行相同的代码,而且二者都须要一个终止条件以免无限循环或者无限递归。对象
/* 函数的递归 -> 就是在指定函数的函数体中调用自身函数 function fun(){ // 当前函数的逻辑内容 console.log('this is function'); // 调用自身函数 -> 实现递归 fun(); } fun(); */ function fn(v){ console.log(v); if (v >= 10) { return; } // fn(v + 1); arguments.callee(v + 1); } fn(0);//致使出错 var f = fn; fn = null; f(0); // console.log(f);
JavaScript能够将函数做为数据使用。做为函数本体,他就像普通的数据同样,不必定要有名字。默认名字的函数被称之为匿名函数。
匿名函数的两种用法:
1.能够将匿名函数做为从参数传递给其余函数。这样,接收函数就能利用所传递的函数来完成某些事请。
2.能够定义某个匿名函数来执行某些一次性任务。递归
JavaScript语法中,定义函数必须定义函数名称 -> 匿名函数 function (){ console.log('this is function'); } 匿名函数的做用: 1.将匿名函数做为参数传递给其余函数 -> 回调函数 2.将匿名函数用于执行一次性任务 -> 自调函数
当一个函数做为参数传递给另外一个函数时,做为参数的函数被称之为回调函数。生命周期
// 做为另外一个函数(fn)的参数的函数(one) -> 回调函数 var one = function(){ return 1; } function fn(v){ return v(); } // one函数仅是做为fn函数的参数出现 -> 并非调用 // var result = fn(one); /* 以上代码等价于如下代码 如下代码中做为参数的函数 -> 匿名回调函数 */ var result = fn(function(){return 1;}); console.log(result);// 1
所谓自调函数就是在定义函数后自行调用。
1.第一对括号的做用,放置的是一个匿名函数。匿名函数接受一个参数
2.第二个对括号的做用,是‘当即调用’。在调用时,向匿名函数传递参数内内容。
自调函数只需将匿名函数的定义放进一对括号中,而后外面在跟一个对括号。
自调函数 - 定义即调用的函数 第一个小括号 - 用于定义函数 第二个小括号 - 用于调用函数 // 全局做用域 - 生命周期:JavaScript文件从执行到执行完毕 (function(value){ // 函数做用域 - 生命周期:从函数调用到调用完毕 console.log('this is ' + value); })('function'); // 表达式语法 (function(value){ // 函数做用域 - 生命周期:从函数调用到调用完毕 console.log('this is ' + value); }('function')); !function(value){ // 函数做用域 - 生命周期:从函数调用到调用完毕 console.log('this is ' + value); }('function'); +function(value){ // 函数做用域 - 生命周期:从函数调用到调用完毕 console.log('this is ' + value); }('function');
将一个函数做为另外一个函数的结果进行返回,做为结果返回的函数称之为做为置的函数。
var one = function(){ return 100; } // 做为值的函数 -> 内部函数的一种特殊用法 function fun(){ var v = 100; // 内部函数 return function(){ return v; }; } var result = fun(); // console.log(result);// one函数 // console.log(result());// 100 console.log(fun()());
不少开发语言中都具备块级做用域,但ECMAScript5版本中并无跨级做用域,这常常会致使理解上的困惑。
虽然ECMAScript5版本没有块级做用域,但具备函数做用域。在某个函数内部定义的变量的做用域就是该函数做用域。
每一段JavaScript代码(全局代码或函数)都有一个与之关联的做用域。这个做用域链是一个对象列表或链表,这组最想定义了这段代码“做用域中”的变量。
var a = 10;// 全局变量 function fun(){ var b = 100;// fun函数做用域的局部变量 // 内部函数 function fn(){ var c = 200;// fn函数做用域的局部变量 // 内部函数 function f(){ var d = 300;// f函数做用域的布局变量 // 调用变量 console.log(a);// 10 console.log(b);// 100 console.log(c);// 200 console.log(d);// 300 } f(); // 调用变量 // console.log(a);// 10 // console.log(b);// 100 // console.log(c);// 200 // console.log(d);// d is not defined } fn(); // 调用变量 // console.log(a);// 10 // console.log(b);// 100 // console.log(c);// c is not defined // console.log(d);// d is not defined } fun();
JavaScript容许函数嵌套,而且内部函数能够访问定义在外部函数中的全部变量和函数,以及外部函数能访问的全部变量和函数。可是,外部函数却不能访问定义在内部函数中的变量和函数。
当内部函数以某种方式呗任何一个外部函数做用域访问时,一个闭包就产生了。
闭包就是词法表示包括没必要计算的变量的函数,也就是说,该函数能使用函数外定义的变量。
var n;// 定义变量,但不初始化值 function fun(){// 函数做用域 var v = 100; // 进行初始化值 -> 一个函数 n = function(){ console.log(v); } // n(); } fun(); n();// 100
闭包的特色和做用特色:1.局部变量:在函数中定义有共享意义的局部变量。2.内部函数:在函数(f)中声明内嵌函数,内嵌函数(g)对函数(f)中的局部变量进行访问。3.外部使用:函数(f)向外返回此内嵌函数(g),外部能够经过此内嵌函数持有并访问声明在函数(f)中的局部变量,而此变量在外部是经过其余途径没法访问的。做用1.提供可共享的局部变量。2.保护共享的局部变量。提供专门的读写变量的函数。3.避免全局污染。