定义函数:将具有一定功能的一段JS代码进行封装
1 function 函数名abs(形参1,形参2){ //()不传参,哑参
2 函数体 3 if (x >= y) { 4 return x; //函数体内部的语句在执行时,执行到return,函数就执行完毕,并将结果返回 5 } else { //没有return语句函数执行完毕也会返回结果,结果为undefined 6 return y; 7 }
8 }
//定义函数:变量初始化函数
1 var 变量名abs = function (形参1,形参2) { 2 函数体
3 if (x >= y) {
4 return x; //function (形参,形参) {}是一个匿名函数,赋值给变量
5 } else { 6 return y;
7 } 8 };
9 var sn = abs(10,20); //函数表达式存储在变量后,变量也就而作为一个函数使用
函数不传参:哑参
函数传参: 可传变量、对象、数组、表达式、函数,可一个可多个
function person(obj,info='朋友’){ return obj.name+','+obj.sex //张三,男 return obj.name+','+obj.sex+info //张三,男朋友 } console.log(person({name:'张三',sex:'男',age:18}))
函数通过关键字function定义
同样可以通过内置的js函数构造器Function()定义
ES5无类的概念,是ES6新增的
new构造函数:创建类
构造函数是用来构建一个类,类是对象的一个抽象符号化表示(把相同或相似的一部分对象抽离出来,形成一个类)对象是类的实例化:
var fn3 = new Function() fn3 = function(n1,n2){ console.log(n1+n2) } fn3(10,20)
构造函数创建类创建对象:
顺序:一)new构造函数,后台执行new Object();
二)new Object()参数代入构造函数的参数;
三)执行构造函数的代码;
四)返回新对象。
function Person(name,age){ //构造函数首字母大写,实际为创建一个类 this.name=name; //this表示实例化后的对象 this.age=age; this.fn = function(){ return this.name+this.age; } } var obj1 = new Person('张三',23); console.log(obj1); //Person{name:"张三",age:23,fn:function()} console.log(obj1.name); //张三 console.log(obj1 instanceof Object); //true console.log(obj1 instanceof Person); //true
console.log(typeof obj); //typeof用来获取data类型,引用类型返回object var arr = [1,2,3]; console.log(arr instanceof Object); //引用类型都属于Object,true console.log(arr instanceof Array); //true
return:带回函数结果
function max(a,b){ var result = a>b? a: b; return result; //结束函数的运行,一般放函数最后 console.log('hahahaha') //不显示 } console.log(max(10,20))
JS有行末自动添加分号,return语句要小心:
function foo() { return { name: 'foo' }; } foo(); // { name: 'foo' } function foo() { return { name: 'foo' }; } foo(); // undefined function foo() { return; // 2相当于自动添加了分号,相当于return undefined; { name: 'foo' }; // 这行语句已经没法执行到了 } function foo() { return { // 这里不会自动加分号,因为{表示语句尚未结束 name: 'foo' }; }
调用函数:函数不会自动执行,必须调用才可以,除立即执行函数(IIFE)外
函数名(实参):
abs(10,3); //返回10,3
abs(10,3,4); //返回10,3
abs(10); //返回10,undefined
避免undefined,可以对参数进行检查:
function abs(x){ if(typeof x !== 'number'){ throw 'Not a Number'; } if (x >= 0) {
return x;
} else {
return -x;
} }
arguments:函数里的对象,只在函数内部起作用,当不确定传的参数个数时使用,可获取全部参数,返回参数列表的一个伪数组
function foo(x){ console.log('x=' + x); //x=10 for (var i=0; i<arguments.length; i++){ console.log('arg' + i + '=' + arguments[i]); //arg 0=10 arg 1=20 arg 2=30 } } foo(10,20,30)
arguments.callee():函数内部属性,递归调用使用
arguments的callee属性,是一个指针,调用函数本身,指向拥有这个arguments对象的函数,用arguments.callee()调用函数也称递归调用
function fact(n){ if(n===1){ return 1; }else{ // return n*fact(n-1); return n*arguments.callee(n-1); } } console.log(fact(6));
rest参数:ES6标准引入
用arguments,获取a,b额外的数组
function foo(a, b) { var i, rest = []; if (arguments.length > 2) { for (i = 2; i<arguments.length; i++) { rest.push(arguments[i]); } } console.log('a = ' + a); console.log('b = ' + b); console.log(rest); }
使用ES6的rest更方便
function foo(a, b, ...rest) { //rest参数只能写在最后,前面用...标识 console.log('a = ' + a); console.log('b = ' + b); console.log(rest); } foo(1, 2, 3, 4, 5); //传入的参数先绑定a、b,多余的参数以数组形式交给变量rest // 结果: // a = 1 // b = 2 // Array [ 3, 4, 5 ] foo(1); //传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined) // 结果: // a = 1 // b = undefined // Array []
箭头函数:ES6新增
(参数1, 参数2, …, 参数N) => { 函数声明 }
(参数1, 参数2, …, 参数N) => 表达式(单一) 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
没有参数的函数:() => {函数声明}
当只有一个参数时,圆括号可写可不写:(单一参数) => {函数声明}
单一参数 => {函数声明}
//ES5 function (x) { return x * x; } //ES6 x => x * x
// ES5 var x = function(x, y) { return x * y; } // ES6 const x = (x, y) => x * y;
箭头函数不需要使用 function、return 关键字及大括号 {}
有的箭头函数都没有自己的 this。 不适合定义一个 对象的方法
当我们使用箭头函数的时候,箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的
箭头函数是不能提升的,所以需要在使用之前定义
使用 const 比使用 var 更安全,因为函数表达式始终是一个常量
箭头函数修复this
的指向,this
总是指向词法作用域,也就是外层调用者obj
var obj = { birth: 1990, getAge: function () { var b = this.birth; // 1990
var fn = function () {
return new Date().getFullYear() - this.birth; // this指向window或undefined,这是不对的,需要用下面的箭头函数
};
var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象 return fn(); } }; obj.getAge(); // 25