作业:日程安排
time 0m
函数基础
time 16m36s
函数定义
time 25m52s
数学中的函数与计算机中的函数有相同之处,也有不同之处
数学函数:输入x 得出y
任意x都有确定的y,x是自变量 y是f(x)函数
解析:在数学中f(x) x其实是指代的意思,f(1)用1替换掉所有x,x是指代、占位符,因为我不知道之后会传什么值,用它指代、占位置,先帮要传的值把位置占上了
学习编程与学习数学类似,公式数学高中公式并不多,数学是理科,不是文科,背诵的并不多
time 28m25s
计算机里面的函数就是函数式编程
函数式编程:用函数封装功能模块,代码复用,解耦合
function test(a,b,c){
//执行语句
}
函数解决什么问题?让代码容易复用
time 30m45s
三种情况想完成一个功能,其实是一个功能
这就有耦合的情况,重复代码块太多了
高内聚 低耦合
time 31m
编程最基本的原则,高内聚低耦合,
高内聚,我们开发的模块,它们代码相关性强,紧密联系比较强
time 32m24s
低耦合:希望把重复的代码,抽象提取出来,组成一个独立的功能体
模块的单一责任制
time 34m22s
一个模块干一件事情
高内聚低耦合,让代码块重复更少
解耦合,在js中,解耦合最常用的方式是函数,函数一般比较常用
time 35m38s
当代码中重复代码多的时候用函数封装重复的部分
如下代码,因为for函数重复次数多,所以用函数封装for函数,重复多的部分
这样如果改成都是0-5就不用改变3处,而只是改变一处就行了
最基本的函数写法 - 函数声明
time 36m23s
用function关键字,var也是关键字
function test(){}
var test=1;
/*function test与var test类似*/
function test (参数){
函数执行语句
}
函数作用
time 38m28s
function就相当于一个电脑,这个电脑是在使用之前已经把软件安装好了,用的时候开机用,不用的时候关闭就行了
比如用函数时test();
函数里面的内容就像电脑里面的软件,安装软件就像代码里面实现的功能,比如电脑里面希望有个英雄联盟,那肯定安装英雄联盟的软件,就有了英雄联盟的功能,类似于在函数中写英雄联盟的功能
函数的功能就像电脑里面的软件,安装软件的过程就是在函数中写代码的过程,
函数执行
time 41m29s
test();
test();
test();
function test(){
console.log('我是很牛的函数');
}
/*
* 我是很牛的函数
我是很牛的函数
我是很牛的函数
*/
只要test()调用函数,函数才会执行,不调用不会执行的
函数命名
time 43m
函数名的命名规则
不能数字开头
字母 数字 下划线 $ 组成
小驼峰命名法 myFunction 复合单词
my_wonderful_test这样也可以,不会报错,但ecma建议、推荐用小驼峰命名法
定义函数的方法
time 45m56s
函数声明的方式去定义,函数内部声明的值,在函数外部不能访问
function test(){
var a=b=1;
console.log(a,b);
}
test();//1 1
console.log(a,b);
/*ReferenceError: a is not defined*/
time 49m23s
表达式,字面量
/**
*表达式 ,也叫字面量
*/
var test=function test(){
var a=1,
b=2;
console.log(a,b);//1 2
}
test();
var test=function test1(){
var a=1,
b=2;
console.log(a,b);//1 2
}
test1();
/*ReferenceError: test1 is not defined
* 报错test1没有被定义*/
/**
* 过程是怎么样的?
* 我声明了一个test变量,之后把function test1这个函数赋值给了test这个变量
*/
time 50m38s
/*这两个是一样的*/
// var test=function (){
var test=function test1(){
var a=1,
b=2;
console.log(a,b);//1 2
}
// test1();
console.log(test.name);//test1
/*因为test赋予test1函数时,就赋予了它功能,test是函数,可以打印1,2的值,这是test的功能
* 当写上test1时是可以忽略的*/
time 51m54s
var test=function test1(){
var a=1,
b=2;
console.log(a,b);//1 2
test1()
// test()
/*都是一样的结果,递归,无限循环了*/
}
console.log(test.name);//test1
test();
函数内部可以调用test1,有它没它是有区别的
time 55m01s
/**
*匿名函数表达式 ,也叫函数字面量
*/
var test = function () {//->匿名函数,因为function没有名字
var a = 1,
b = 2;
console.log(a, b);//1 2
}
console.log(test.name);//test
test();
字面量
time 55m42s
var a = 10;/*10就是字面量*/
var a = "我爱编程";/*也是字面量*/
var a = [];/*数组也是字面量*/
var a = {};/*对象也是字面量*/
var a =function () {
} ;
/*函数也是字面量,把一个函数赋值给test、a就是变量,赋值给一个变量
* 赋值的过程,函数就是字面量了*/
函数的组成部分
time 56m52s
function函数名 参数(可选) 返回值(可选) return没有返回值返回undefined
function 函数名 参数(可选) 返回值(可选) return代码自动在后面加上,没有返回值返回undefined
function test() {
var a = 1,
b = 2;
console.log(a + b);
}
test();//3
这里面a,b是在函数里面声明的值,外界不能用a、b的值,不能改变a、b的值,test()运行永远打印3,打印不了别的
现在,我想让函数可以打印别的值,可以修改a、b的值,这样只能在参数里面写a、b
function test(a, b) {
/* var a = 1,
b = 2;*/
console.log(a + b);
}
test(1, 2);//3
time 1h2m7s
var aa = Number(window.prompt('a'));
var bb = Number(window.prompt('b'));
function test(a, b) {
// var a, b;//就相当于在外界声明一个a,b
console.log(a + b);
}
test(aa, bb);
function test(a, b) {
var a, b;//就相当于在外界声明一个a,b
console.log(a + b);
}
test(1,2);//3
形参实参的区别、关系
time 1h3m25s
/*占位->形式上占位,形式参数 形参*/
function test(a, b) {
var a, b;//就相当于在外界声明一个a,b
console.log(a + b);
}
/*调用函数,函数运行,传入实参,1、2是实参*/
test(1,2);//3
形参实参,形参是占位符
实参只有在test(aa,bb)函数运行时的赋予的值,aa、bb都是实参
a、b以及函数里面的都是形参,因为函数不运行,不知道传入的是什么参数,所以用形参来占位指代,相当于f(x)=2x的x,指代要传入的值
参数顺序
time 1h5m22s
函数顺序不能颠倒
总结
time 1h5m56s
参数有点像函数内部声明的变量,类似于函数内部声明的变量
不同之处是参数可以在函数调用时赋值,函数内部声明变量无法在函数调用时赋值,改变
function test() {
var a, b;
console.log(a + b);
}
/*调用函数,函数运行,传入实参,1、2是实参*/
test(1,2);//3
调用时改变不了a、b
function test() {
var a, b;
/*想在函数调用时改变这里面的a、b,现在肯定改变不了*/
console.log(a + b);
}
test(1,2);//NaN
如果想在函数调用是改变某个值,不想让函数中某个值是定值,不可以改变,就把它作为参数
function test(a, b) {
// var a, b;
/*想在函数调用时改变这里面的a、b,现在肯定改变不了*/
console.log(a + b);
}
test(1, 2);//3
函数参数传递时,参数的数据类型不会变
time 1h7m10s
没有数据类型的限制,什么数据类型都可以传进去
function test(a, b) {
console.log(a, b);
}
test(1, 2);//1 2
test('false', NaN);//false NaN
形参与实参数量可不等
time 1h7m58s
形参与实参个数对不上不会报错
形参与实参数量可不等
function test(a, b, c) {
console.log(a, b, c);
}
test(1, 2);//1 2 undefined
arguments
time 1h11m56s
既然实参、形参个数可不等,那么函数能不能知道传递了那些实参?
用arguments可以知道
function test(a, b) {
console.log(a, b);
console.log(arguments);
}
test(1, 2, 3);
arguments有length可以进行for循环
time 1h13m33s
arguments有length可以进行for循环
function test(a, b) {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
test(1, 2, 3);//1 2 3
形参的长度也可以知道,用函数.length
time 1h14m33s
形参的长度也可以知道,用函数.length
function test(a, b) {
console.log(test.length);//2
console.log(arguments.length);//3
}
test(1, 2, 3);
根据输入实参,求累加和
time 1h15m50s
最大的问题,不知道实参的个数与值?利用arguments
// 一个函数被调用时,累加它的实参值
function sum() {
var _length = arguments.length;
var sum = 0;
for (var i = 0; i < _length; i++) {
sum += arguments[i];
}
console.log(sum);
}
sum(1, 2, 3);
可以在函数内部更改实参的值
time 1h21m49s
可以在函数内部更改实参的值
这样也符合常理,比如用户填了一个不合法的值,我可以改变这个值
function test(a, b) {
a = 3;
console.log(arguments[0]);//3
}
test(1, 2);
只能修改传入值的实参的值
time 1h23m12s
实参没有传b,不能改变,因为调用函数时没有给b赋值,没有b的实参,是undefined,没有实参b,所以更改不了实参
实参b,形参b,形参b可以改变,打印为3
function test(a, b) {
b = 3;
console.log(b);//3
console.log(arguments[1]);//undefined
}
test(1);
行实参有映射关系
time 1h26m43s
a与arguments[0]是不是一个变量产生的值,是不是一个东西
function test(a, b) {
a = 3;
console.log(arguments[0]);//3
}
test(1, 2);
不是。因为a是原始值存在栈内存,而argument是引用值,存在对内参,arguments[0]是arguments对象上面的引用值,有新的地址,与a的地址不一样。
argument[0]与a不是一个东西,存储地方不同,但有映射关系
a=3 a存栈内存里,argument[0]存堆内存里
实参与形参是不同的量,存在不同的地方,但是系统里有映射关系,无论实参怎么赋值,形参都会改变,但一定形参数组里面有对应的值才行,如果没有对应的值没有用,有映射关系,给形参赋值实参也会改变
参数有没有映射关系看一开始函数运行时给他赋予参数了没有,即使是undefined也行,不写写个,不行
return
没写return的情况,js引擎自动添加
function test(){
console.log('我正在执行');
console.log('我正在执行了就结束这个函数');
/*不是运行完最会一句console就完事了的*/
}
function test(){
console.log('我正在执行');
console.log('我正在执行了就结束这个函数');
/*不是运行完最会一句console就完事了的*/
return;
/*js引擎自动默认加了一个return来结束函数,隐式添加一个return,偷偷摸摸添加*/
}
return终止函数运行
time 1h33m37s
下面的console是不会执行的,return写在哪里下面函数是不会执行的
function test(){
console.log('我正在执行');
return;
console.log('我正在执行了就结束这个函数');
}
console.log(test());
/*我正在执行
undefined*/
应用
time 1h35m12s
判断空值,结束函数,有值打印
设置默认值,判断
return两种作用1返回相应的值 2终止函数运行
time 1h41m26s
会打印两个,因为console没有终止函数运行,函数继续运行
time 1h44m29s
function test(name) {
return name || '你没有填写姓名';
}
console.log(test()); // '你没有填写姓名'
全局变量与局部变量
time 1h53m14s
总结
time 2h5m25s
函数式编程是什么?
布置作业
time 2h11m34s
arguments
1.类数组对象。
2.存储实参列表。
3.可以在函数内部修改传入的实参值。
4.实参未传入时,在函数内部给行参赋值无效。
三、变量类型
3.1 全局变量
1.在全局环境下声明的变量在任何地方都可以访问。
2.在函数内定义变量时省略var操作符,可以创建一个全局变量。只要调用一次该函数,就会定义这个变量,并且可以在函数外部访问到。
3.2 局部变量
使用var操作符定义的变量会成为包含它的函数的局部变量,该变量将在函数退出时销毁。
// 全局变量
a = 1;
function test1() {
// 局部变量
var b = 2;
console.log(a, b); // 1 2
// 重新赋值全局变量a a -> 4
a = 4;
function test2() {
// 局部变量
var c = 3;
// 重新赋值test1内的变量b b -> 5
b = 5;
console.log(b); // 5
}
test2();
// test2函数运行完时局部变量c被销毁
console.log(c); // ReferenceError
}
test1();
函数封装的是一个一个的功能,功能是输入x,输出y,输入就是参数,输出就是return
函数最好都有参数与返回值
四、作业
4.1 定义一个函数,从wp接收一个饮料的名称,函数返回对应的价格
function test1(name) {
switch (name) {
case '可乐':
console.log('3¥');
break;
case '矿泉水':
console.log('1¥');
break;
case '脉动':
console.log('5¥');
break;
case '营养快线':
console.log('4¥');
break;
default:
console.log('无');
}
}
var name = window.prompt('请输入饮料的名称');
test1(name);
4.2 定义一个函数,从wp接收第一个数,接收一个运算符号(+ - * / %),接收第二个数,利用这个函数做运算,并返回运算结果
function test2(value1, type, value2) {
switch (type) {
case '+':
console.log(value1 + value2);
break;
case '-':
console.log(value1 - value2);
break;
case '*':
console.log(value1 * value2);
break;
case '/':
console.log(value1 / value2);
break;
case '%':
console.log(a % b);
break;
default:
console.log('输入格式错误');
}
}
var value1 = Number(window.prompt('请输入第一个数字'));
var type = window.prompt('请输入运算符');
var value2 = Number(window.prompt('请输入第二个数字'));
test2(value1, type, value2);
4.3 定义一个函数,从wp接收一个n,算出n的阶乘,不能用for循环
function test3(n) {
if (n < 0) {
return '请输入一个正整数';
}
if (n === 0) {
return 1;
} else if (n > 0){
return test3(n - 1) * n;
}
}
var n = parseInt(window.prompt('请输入一个正整数'));
console.log(test3(n));
4.4 定义一个函数,从wp接收一个n,算出斐波那契数列的第n项,不能用for循环
function test4(n) {
if (n <= 0) {
return 0;
}
if (n === 1 || n === 2) {
return 1;
} else {
return test3(n - 1) + test3(n - 2);
}
}
var n = parseInt(window.prompt('请输入一个正整数'));
console.log(test4(n));
扩展总结思考
问题
这节课讲了什么?
函数的声明、作用
形参实参
argument
return
函数的作用是什么?意义何在?