JavaScripts基础(5)函数数据类型

330 阅读5分钟

函数 :具备一定功能的方法

函数诞生的目的就是为了实现封装:把现实一个功能的代码封装到一个函数中,后期想要实现这个功能,只需要把函数执行即可,不必再次编写重复的代码,起到低耦合高内聚(减少页面冗余代码,提高代码的重复使用率)的作用,我们把以上特点叫做函数封装

OOP面向对象编程思想,需要我们掌握类的继承、封装、多态

函数数据类型也是按照引用地址操作的

ES3function 函数名([参数]){
		函数体:实现功能的js代码
	}
    函数名();
    
ES6箭头函数:
	let 函数名 =([参数])=>{
		函数体
    }
    函数名();
function  fn(){
//代码	
}
fn;   //=>输出函数本身
fn(); //=>函数执行

let fn=()=>{

}
fn();

创建函数:

1、先创建一个变量(声明一个函数名和声明一个变量一样 ,如果两个变量名重复 是会冲突的)

2、开一个新的内存空间(为其分配了一个16进制的地址)

3、把函数体中编写的js代码当做 “字符串” 存储到空间当中(所以函数只创建不执行没有意义)

4、把分配的地址赋值给声明的函数名function fn(){}var fn=function(){} 两种生命的方式 操作原理相同,都是在当前作用域中声明了一个名字,此处两个名字是重复的)

执行函数:

目的:执行函数体中的代码

1、函数每次执行的时候 浏览器都会形成一个新的私有作用域也就是栈内存(只能执行函数体中的代码),函数体中的代码执行

2、执行代码之前先把创建函数的字符串 复制过来 变为真正的js表达式,按照从上到下的顺序在私有作用域中执行

一个函数可以被执行N次,每次执行相互之间互不干扰,因为每次执行函数都会执行上边的步骤 重新创建私有作用域

函数中的参数

形参:是一个变量,函数的入口

当我们创建一个函数想要实现某个功能的时候,发现有一些材料并不清楚,只有当函数运行的时候,别人传递给我我才知道,此时我们就需要设定入口,让用户执行的时候 通过入口把值给我们

形参默认值设置

一. 基本用法
function first(x = 1, y = 2) {
    console.log("x:"+x ,"y:"+ y);
}
first();		//x:1 y:2
first(100);		

二.与解构赋值默认值结合
function second({x, y = 2}) {
    console.log("x:"+x ,"y:"+ y);
}
second();               //报错  Uncaught TypeError: Cannot destructure property `x` of 'undefined' or 'null'
second({});             //x: undefined   y:2
second({x:100});        //x: 100    y:2
second({x:100,y:200});  //x: 100    y:200

三.双重默认值
function third({x = 1 ,y = 2} = {}) {
    console.log("x:"+x ,"y:"+ y);
}
third();                //x: 1    y:2
third({x:100,y:200});   //x: 100  y:200
third({x:100});         //x: 100  y:2

//步骤解析
function third(option = {}){   
	let {x=1,y=2}=option 
}
third({x:100,y:200});

实参:是具体值

函数执行时传递给函数形参的**具体值**就是实参(实参是具体值)

实参一定是值,即使我们写的是变量或者表达式,也是把变量或者表达式计算的结果作为值传递给形参变量

//形参
function  fn(num1,num2){
    console.log(num1,num2)
    var total=num1+num2;
    return total;   // 并不是把变量total返回,而是把变量total代表的值返回
}

//实参
fn(10,12); //=>函数执行
var a=16;
fn(a,1===1?10:0)

函数的返回值:函数出口

1、返回值 return,把函数运行的结果(或者函数体中的部分信息)拿到函数外面去使用

2、return 返回的永远是一个值(即使return一个变量也是return变量代表的值)

3、如果函数执行没有return结果出来(或者 return;啥也没返回),函数执行在外面拿到的结果都是undefined

4、return 之后的代码不再执行,强制结束函数的执行

function  fn(num1,num2){
	var total=num1+num2;
	return total;  
}
fn(10,12); //=>22
var res=fn(10,12);
console.log(res)  //22

//--------------------------------

function  fn(num1,num2){
	var total=num1+num2;
}
var res=fn(10,12);
console.log(res)  //undefined

arguments:内置的实参集合

形参有局限性:我们需要具体的知道用户执行的时候传递实参的数量、顺序等,才可以用形参定义对应的入口

arguments:是函数内置的实参集合

arguments是函数天生就存在的机制,不管你是否设置了形参,也不管你是否传递了实参,arguments都有

arguments是类数组(不是数组,不能用数组里边的方法)__proto__指向Object,普通数组__proto__指向Array;但是获取方法跟数组一样:arguments[0],arguments.length

即使设置了形参变量,形参该是什么是什么,但是arguments始终存储的是“所有”传递进来的实参

arguments.callee:存储的是当前函数本身

function sum(n,m){
/*
	console.log(arguments)
	{
		0:10,
		1:20,
		length:2,
		callee:存储的是当前函数本身 arguments.callee===sum   true
	}
*/

	
}
sum(10,20)
//任意数求和,不管函数执行时传递多少实参值进来,都可以求和
//把实参值依次遍历,求和
//累加的时候,把字符串转化为数字,对于一些非有效数字,不再相加
function sum(n,m){
	var  total=null;
	for(var i=0;i<arguments.length;i++){
		var item=arguments[i];
		//不管item是什么类型都转化为数字类型
		item=Number(item);
		//如果当前的值是有效数字才累加
		isNaN(item)?null:total+=item;
	}
	return total;
}
sum(10,2030)   // 60
sum(10,'20','aaa')     //30

ES6写法:

let sum=(...arg)=>{
//arg为数组类型
	arg=arg.filter(item => !isNaN(item));
	return eval(arg.join('+'));
}
sum(10,'20','aaa')     //30

//简写
let sum=(...arg)=> eval(arg.filter(item => !isNaN(item)).join('+'));

实名函数 匿名函数

实名函数:有函数名

function fn(){

}

匿名函数:没有函数名的

函数表达式:把函数当做值赋值给变量或者元素的事件

//函数表达式
var fn=function(){

}
oBox.onclick=function(){

}

自执行函数:创建和执行一起完成

//自执行函数
(function(i){
})(10)

~function(){
}()
+function(){
}()
!function(){
}()

// -、+、~、!只是让代码符合语法而已,没有实际意义