函数 :具备一定功能的方法
函数诞生的目的就是为了实现封装:
把现实一个功能的代码封装到一个函数中,后期想要实现这个功能,只需要把函数执行即可,不必再次编写重复的代码,起到低耦合高内聚(减少页面冗余代码,提高代码的重复使用率)
的作用,我们把以上特点叫做函数封装
OOP
面向对象编程思想,需要我们掌握类的继承、封装、多态
函数数据类型也是按照引用地址操作的
ES3:
function 函数名([参数]){
函数体:实现功能的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,20,30) // 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(){
}()
// -、+、~、!只是让代码符合语法而已,没有实际意义