JavaScript函数
- 1、函数的介绍
- 2、函数的使用
- 3、特殊函数
- 3.1、匿名函数
- 3.2、递归函数
- 3.3、回调函数
- 3.4、闭包函数
- 4、使用 arguments 对象
- 5、函数参数
- 5.1、默认参数
- 5.2、剩余参数
- 6、箭头函数
JavaScript函数:执行特定功能的代码块。[类似于java中的方法]
1、函数的介绍
- JS函数,我们在定义后,它是全局性的,我们可以任意调用。
- Js函数定义在外部Js文件中,实现代码重用。
- Js函数可以有返回值,也可以是无返回值(功能性函数)。
- 可以在一个函数中调用另一个函数,也可以把一个函数的返回值作为另一个函数的参数。
Js函数分为: 系统函数和自定义函数。
Js变量作用域: 变量使用的有效范围,在 JavaScript 中,对象和函数同样也是变量。
- 全局变量:声明在所有函数之外的变量,称为全局变量,页面关闭后销毁。
- 局部变量:声明在函数内部的变量,仅供该函数使用,函数运行完毕后销毁。
2、函数的使用
// 方式一:预解析阶段函数会提升
function fn() {};
// 方式二:预解析阶段只会提升函数名,后面的函数体 function() {}不会提升
var fn1 = function() {};
//调用函数
fn();// 有参函数,这里的参数为形参(定义时)
function fn2(x,y){console.log(x+"-"+y);
}
// 调用有参函数
fn2(6,8); //输出 6-8,这里的参数为实参(调用时)// return表示立即退出函数,并设置函数的返回值
function fn3(){return 666;
}
console.log(fn3()); //输出666
3、特殊函数
3.1、匿名函数
匿名函数是指没有名字的函数,通常用于函数表达式。
let hello = function (){console.log("web-chubby"); } //立刻调用函数表达式: (function () { //函数体 })(); //后面这对圆括号中可加参数,去掉圆括号表示不执行该函数
3.2、递归函数
递归函数是自己指向并调用自己,分为递推和回归两个过程,需要终止条件并且逐步向终止条件靠近,递归函数使用了堆栈:
function foo(i) {if (i < 0)return;console.log('begin:' + i);foo(i - 1);console.log('end:' + i); } foo(3);// 输出:// begin:3 // begin:2 // begin:1 // begin:0 // end:0 // end:1 // end:2 // end:3
3.3、回调函数
回调函数是将一个函数作为另一个函数的参数,这个作为参数的函数可以为一个函数名、普通函数、匿名函数等等。
回调函数通常与异步函数一起使用,因为在异步的情况下才能真正体现出回调函数的作用。
在大多数编程语言中,函数的形参总是由外往内向函数体传递参数,但在JS里如果形参是关键字"callback"则完全相反,它表示函数体在完成某种操作后由内向外调用某个外部函数。
let fs = require("fs");function f(x) {console.log(x) }function writeFile(callback) { //关键字callback,表示这个参数不是一个普通变量,而是一个函数fs.writeFile('input.txt', '我是通过fs.writeFile 写入文件的内容', function (err) {if (!err) {console.log("文件写入完毕!")c = 1callback(c) // 因为我们传进来的函数名是f(),所以此行相当于调用一次f(c)}}); } let c = 0 writeFile(f) // 函数f作为一个实参传进writeFile函数
3.4、闭包函数
在一个函数内部再定义一个函数,此时再定义的函数称为闭包函数,内部函数只可以在外部函数中访问。
内部函数形成了一个闭包:它可以访问外部函数的参数和变量,但是外部函数却不能使用它的参数和变量。
如果一个闭包的函数定义了一个和外部函数的某个变量名称相同的变量,那么这个闭包将无法引用外部函数的这个变量。
function addSquares(a, b) {function square(x) {return x * x;}return square(a) + square(b); } a = addSquares(2, 3); // returns 13 b = addSquares(3, 4); // returns 25 c = addSquares(4, 5); // returns 41// 调用外部函数并为外部函数和内部函数指定参数 function outside(x) {function inside(y) {return x + y;}return inside; } fn_inside = outside(3); // 可以这样想:给一个函数,使它的值加 3 /* 一个闭包必须保存它可见作用域中所有参数和变量。 每一次对外部函数的调用实际上重新创建了一遍这个闭包。 只有当返回的 inside 没有再被引用时,内存才会被释放,所以x的值还在 */ result = fn_inside(5); // returns 8 result1 = outside(3)(5); // returns 8 ,先调外部函数,再调内部函数
4、使用 arguments 对象
函数的实参会被保存在一个类似数组的 arguments 对象中,可以通过类似于如下这种方式找出传入的参数:
function myConcat(separator) {var result = ''; // 把值初始化成一个字符串,这样就可以用来保存字符串了!!var i;// 遍历参数for (i = 1; i < arguments.length; i++) {result += arguments[i] + separator;}return result; } myConcat(", ", "red", "orange", "blue"); // returns "red, orange, blue, " myConcat("; ", "elephant", "giraffe", "lion", "cheetah"); // returns "elephant; giraffe; lion; cheetah; " myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley"); // returns "sage. basil. oregano. pepper. parsley. "
arguments
变量只是“类数组对象”,并不是一个数组。称其为类数组对象是说它有一个索引编号和length
属性。尽管如此,它并不拥有全部的 Array 对象的操作方法。
5、函数参数
从 ES6 开始,有两个新的类型的参数:默认参数,剩余参数。
5.1、默认参数
// 在形参列表中直接给参数赋值,这样就可以免去一些判断未定义的操作
function multiply(a, b = 1) {return a*b;
}
multiply(5); // 5
5.2、剩余参数
// 剩余参数语法允许将不确定数量的参数表示为数组
function multiply(multiplier, ...theArgs) {return theArgs.map(x => multiplier * x);
}
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
6、箭头函数
箭头函数表达式相比函数表达式具有较短的语法并以词法的方式绑定
this
。箭头函数总是匿名的。
var a = ["Hydrogen","Helium","Lithium","Beryllium"];var a2 = a.map(function(s){ return s.length }); console.log(a2); // logs [ 8, 6, 7, 9 ]var a3 = a.map( s => s.length ); console.log(a3); // logs [ 8, 6, 7, 9 ]
不用箭头函数,this为全局对象:
function Person() {this.age = 0; // 构造函数 Person() 将`this`定义为自身setInterval(function growUp() {// 在非严格模式下,growUp() 函数将`this`定义为“全局对象”,这与 Person() 定义的`this`不同this.age++; //this指向全局对象,所以age还是0}, 1000);
}
var p = new Person();
将this值赋给一个变量,解决上述问题:
function Person() {var self = this; self.age = 0;setInterval(function growUp() {self.age++; // this指向person对象}, 1000);
}
箭头函数捕捉闭包上下文的this值,简单实用:
function Person(){this.age = 0;setInterval(() => {this.age++; // this指向person对象}, 1000);
}
var p = new Person();