一. 函数
1. 函数概念
- 定义:函数是具有某种特定功能的代码块
- 本质:函数其实本质也是一种数据,属于对象数据类型。
- 作用:
-
- 解决代码的冗余问题,形成代码复用
- 可以把整个代码项目通过函数模块化
-
- 封装代码,让函数内部代码对外不可见
2. 函数组成
- 组成:
-
- 函数名:命名规则同变量名一致
- 函数体:函数的内容,代码块
-
- 参数:形参和实参
- 返回值:函数调用表达式的结果
- 声明代码:
声明 function 函数名(形参1,形参2……){函数体 return返回值}
调用 函数名()
3. 定义函数的三种方式
- function关键字方式/字面量方式
function 函数名() {
}
function 函数名(参数) {
}
- 表达式方式
var 函数名 = function(){
}
var 函数名 = function(参数) {
}
- function构造函数方式
var 函数名 = new Function('函数体');
var 函数名 = new Function('参数', '函数体')
4. 函数调用
- 函数调用表达式:函数名() 表达式的值就是函数的返回值
- 函数名本质上是变量,后边不加()不会调用,函数内的代码也不会执行
5. 函数的返回值
- 返回值
- return:函数体内的return右边的表达式(变量/直接量)便是函数的返回值
- 函数名()的值就是函数的返回值
- 函数体内没有写return或者return右边是空的,默认值会返回undefined
- return除了设置返回值外,还可以结束函数的执行,return之后的代码不会执行
- break:这个可以打破循环直接返回
- continue:返回循环本身继续循环
let btn = document.getElementById('btn')
let h1 = document.getElementById('h1')
//给btn的onclick事件绑定一个函数
btn.onclick = function(){
if(flag){
h1.style.display = 'none';
flag = false;
return //条件一旦成立,那么return下边的代码就不再执行
}
h1.style.display = 'block';
flag = ture;
}
- 那些函数需要返回值
- 用作计算,最后的计算结果需要使用时需要写返回值
- 函数的功能是实现某个具体的操作(界面操作),无需返回值
6. 函数的参数
- 形参和实参
- 形参:声明函数的时候,给的参数,类似于变量名
- 实参:调用函数时给的值,类似于赋值
- 形参和实参数量问题
- 正常情况下,实参数量等于形参数量
- 如果实参数量大于形参数量,多出来的实参,将被省略,如若想导出全部实参可借鉴arguments说明
- 如果实参数量小于形参数量,有的形参没有确定的实参,取默认值undefined 。
- 形参的默认值
- js函数允许形参有默认值,有默认值的形参,再调用函数时,可以没有与之对应的实参
- 默认值的设置(es6):function(b,a=0){}
- 默认值设置(es5):function(a,b){ a=a||0;b=b||0 }
function add(a,b){
//需要给a,b设置默认值0
//提升代码健壮性(容错率)
//es5这样写
a = a||0;
b = b||0;
return a + b
}
function f1(a=1){
//这种赋予默认值的条件就是 只要a对应的实参不是null 赋予默认值都不起作用
console.log(a);
}
/*
创造函数
function 函数名(形参){}
*/
- 注意:有默认值的形参一定要放在后边!
- arguments
- 只能在函数内使用
- arguments是一个类数组对象,具有数组的一些特性
- arguments可以获得所有的实参,所以我们想获取实参的话有两种方式:用形参;使用arguments。
- 用途:计算所有此参数和,取参数中的最大值,取参数中的最小值,求所有参数平均值
/*通过arguments取所有参数里面的最大值
*/
function max() {
//设置遍历 默认值的最大值
var res = arguments[0];
// 循环比较
for (var i = 0; i < arguments.length; i ++) {
if (arguments[i] > res) {
res = arguments[i];
}
}
// 返回结果
return res;
}
/**
* 取所有参数里面的最小值
*/
function min() {
var res = arguments[0];
// 循环比较
for (var i = 0; i < arguments.length; i ++) {
if (arguments[i] < res) {
res = arguments[i];
}
}
// 返回结果
return res;
}
/**
* 取所有参数的和
*/
function total() {
var res = 0;
for (var i = 0; i < arguments.length; i++) {
res += arguments[i];
}
return res
}
console.log(total(1, 2, 3, 4, 5))
/**
* 取所有参数的平均数
*/
function average() {
var res = 0, ave = 0;
for (var i = 0; i < arguments.length; i++) {
res += arguments[i];
}
ave = res / arguments.length;
return ave
}
console.log(average(1, 1, 4));
\
7. 函数的嵌套
- 函数体内可以嵌套函数
8.自调用函数IIFE(Immediately Invoked Function Expression)
- 匿名函数
- 定义:即没有名字的函数
- 注意:匿名函数声明完要立即调用,否则没有意义
function() {
//匿名函数
}
- 自调用函数
- 函数声明完立即调用,称之为自调用函数,也叫立即调用函数,英文简称IIFE, 英文全称Immediately Invoked Function Expression。
// 函数允许匿名,但是匿名的函数要立即使用
// 自调用函数,立即调用函数
(function(){
console.log('哈哈哈,我被调用了');
})();
// 自调用函数 传参
(function(a, b){
console.log(a+'和'+b+'跳舞');
})('曹操', '刘姥姥');
// 当然不匿名的自调用函数也是可以的,不过没有意义
(function fn(){
console.log('fn 被调用了');
})();
(function(){})();
~function(){}();
+function(){}();
-function(){}();
!function(){}();
- 注意
- 两个连续的自调用函数之间必须加分号,告诉浏览器是不同的函数,否则会有语法错误。
- 在后边的自调用函数前加 '!' 等没有副作用的一元运算符也可以起隔离作用
练习
//开关灯实例练习
//场景:仿照小说的夜间日间模式设置开关灯案件
<body>
<button>开灯</button>
<button>关灯</button>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
<script>
let btn = document.getElementsByTagName('button');
console.log(btn[0],btn[1]);
let body = document.body;
let h=document.getElementsByTagName('h1')
btn[0].style.display = 'none'
//ture时为开灯false为关灯
btn[1].onclick = function () {
btn[1].style.display = 'none'
btn[0].style.display = 'block'
body.style.background = 'black';
body.style.color = "#FFF";
}
btn[0].onclick = function () {
btn[0].style.display = 'none'
btn[1].style.display = 'block'
body.style.background = '#fff';
body.style.color = 'black';
}
</script>
</body>
9. 箭头函数(es6新增)
- 函数代码:var 函数名=(形参1,形参2……)=>{return 返回值};
- 如果形参只有一个,那小括号可以省略
- 如果函数体只有return一条语句,那大括号也可以省去
- 箭头函数不能使用arguments
- this也不能使用
//转换为箭头函数
function (a,b){
ruturn a+b;
}
// var f=(a,b)=>{ return a+b;};
//箭头函数转换为字面量式/表达式
var result = index => index + 1;
function result(index) {
return index + 1;
};
var result = function(){
return index + 1;
};
10. caller和callee
- caller:全局变量
- callee:局部变量
function outer(){
//函数执行的宿主环境,如果是全局,那就是null
console.log(outer.caller);
inner();
};
function inner(){
//函数身上有个caller inner在outer里面调用,宿主环境就是outer
console.log(inner.caller);//outer函数
console.log(arguments.callee);//函数本身
console.log(arguments.callee.caller);//outer
}
11. 选项卡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
.container {
width: 1000px;
margin: 0 auto;
}
.container>div {
width: 600px;
height: 300px;
text-align: center;
line-height: 300px;
display: none;
}
.container>.current {
background: red;
display: block;
}
ul>.current {
background: green;
}
ul {
font-size: 0;
}
ul>li {
display: inline-block;
width: 100px;
height: 80px;
line-height: 80px;
text-align: center;
font-size: 22px;
}
</style>
</head>
<body>
<div class="container">
<ul>
<li class="current">吃饭</li>
<li>睡觉</li>
<li>打豆豆</li>
</ul>
<div class="current">不吃饭</div>
<div>不睡觉</div>
<div>不打豆豆</div>
</div>
<script>
let list = document.querySelectorAll('li');
let box = document.querySelectorAll('.container div');
for (var i = 0; i < list.length; i++) {
list[i].record = i;
list[i].onclick = function () {
for (var a = 0; a < list.length; a++) {
list[a].className = '';
box[a].className = '';
}
this.className = 'current';
box[this.record].className = 'current';
}
}
</script>
</body>
</html>
12. 补充
- this:指事件绑定的元素
- debugger:断点
- argument,this都是函数中特殊的存在