前端零基础 JS 教学 第四天 04 - day 函数 重点啊重点

复习: 第三天课程

1、数组创建方法 2种方法
	答:1、var  arr = new Array(); 使用 new  Array 方法 
	答:2、var arr = [] 字面量方式
2、var arr = [1,2,3,4];说出什么是数组元素,什么是下标
	答 :[1,2,3,4] 是数组元素 ,下标是序号0,1,2....开始的 
3、如何获取数组的长度
	答:length  就是数组的个数
4、如何遍历数组
	答:for 从头到尾选择的for里面有个i 当索引号看
5、增加数组元素是如何实现的
	答:数组名[索引号] = '值'
	arr[0] = 123,
6、为什么需要函数
	答:代码多次复用,多次调用
7、函数是怎么声明的和调用的
	答:function 声明 使用 函数名加小括号  调用  function fn(){} fn(); 
8、function f(x,y){xxxx} f(1,3) 请说出那个是实参那个是形参
	答:f(1,3)实参, f(x,y)是形参,x,y相当于变量
9、函数的返回值,是返回给谁的?
	答:return  谁调用return 返回给谁
复制代码

今天全天都讲函数:就是这么多 对我来说都很重要

每个练习题我会详细讲到每个步骤

		1、函数练习
		2、函数参数和返回值注意事项
		3、arguments 的使用
		4、定义函数的两种方式
		5、自执行函数
		6、函数也是一种数据类型 function
		7、函数可以作为参数 
		8、函数可以作为返回值
		
		9、作用域
		10、作用域链
		11、预解析 
复制代码

1、练习

1、函数 封装 翻转数组

思路:
	1、翻转数组,返回一个新数组
	2、把内容封装到函数里面去reverse 反转 reverse记住后面有个方法 

//这里的arr 是形参 
function reverse(arr){
	// 新数组接收方
	var newArr = [];
	// 遍历循环
	for(var i=0; i<arr.length;i++){
		// 接收方 		旧数组长度 - i-1,每次循环都给一次
		newArr[i] = arr[arr.length-i-1];
	}
	// 谁调用给谁,不然就会undefined
	return newArr;
}
//把数组要传输到函数里面通过 形参  参数 传递 
var arr = [1,2,3,4,5]; //这个arr 是数组名
reverse(arr); //函数调用是 实参 

// 打印数组 翻转成功
console.log(reverse(arr));
// 第二种数组传参方法   
console.log(reverse(['red','pink','green']));



2、函数 封装冒泡
    
    //冒泡 需要两个for 循环 外层 for 需要趟数 长度减去 1
	// 里层的for 循环 管交换次数  长度 减去 i 减去 1
	// 交换2个值  
	// 后面会学到sort 算法 
	function sort(arr){
		for(var i=0; i<arr.length-1;i++){
			for(var j=0; j<arr.length-i-1;j++){
				// 比较 arr[j] 是0 开始比较 
				if(arr[j] < arr[j+1]){
					var temp = arr[j];  //保存第一个 
					arr[j] = arr[j+1]; //第二个给第一个
					arr[j+1] = temp; 
				}					
			}
		}
		// return 出去 
		return arr;
	}
	var arr = [1,3,5,7,8,10];
	console.log(sort(arr))



3、函数 封装闰年

    //函数 需要接受的年份,能被4这整除 并且不能被100整除,或者能被400 整除 
function isRun(year){
	// 这里的flag 一个变量来控制 用来存储 是不是闰年的 
	var flag = false; //刚开始默认的就是false  默认的是 平年 flag 是开关 
	// 你这里的条件是不是闰年啊?
	if(year % 4 === 0 && year % 100 !==0 || year % 400 ===0 ){
		//是true 就会覆盖掉了,flag 里面存储的要么是true要不就是false 
		flag = true;
	}
	// 然后return 出去 
	return flag 
}
console.log(isRun(2019));



4、计算2019年2月15日是一年中的第几天 

这个案例的核心就函数可以调用函数

    	//获得天数的函数 
	function getDays(year,month,day){
		// days 存储的总天数,
		// day先存储当月的天数
		// var days = 0;
		//  days += day;

		 var days = day

		// 月份有很多我们需要for 循环,详细介绍当月天数只能从 1月份开始,小于你输入的天数 
		for(var i=1; i<month; i++){
			switch (i) {
				case 1 :
				case 3 :
				case 5 :
				case 7 :
				case 8 :
				case 10 :
				case 12 :
					days += 31;
					break;
				case 4:
				case 6:
				case 9:
				case 11:
					days +=30;
					break;
				case 2:
				// 如果是闰年 +=29年 
				// 否则是平年 +=28天
				// 在函数里面右调用了一个函数 
				if(getRun(year)){
					days+=29;
				}else {
					days+=28;
				}
				break;
			}
		}
		// 先return days
		return days
	}
	console.log(getDays(2018,2,15));


	// 这里我们拿到之前写的函数 进行平年润年的判断
	function getRun(year){
		var flag = false;
		if(year % 4 === 0 && year % 100 !==0 ||year % 400 === 0){
			flag = true
		}
		return flag;
	}
	
思路:
	1、输入某年某月某日判断这一天是这一年的第几天
	2、比如要输入年份,因为有闰年和平年,也要区分开
	3、月份不一样 有的是30天 有的是31天 
	4、先算当月的天数
	5、前面几个月的总天数 + 不断的相加 for 循环 
复制代码

斐波那契额数列:1,1,2,3,5,8,13,21

会发现处理第一个和第二个之外 后面第三个都是前一个数字相加

//思路就是 
		var n1 = 1;
		var n2 = 1;
		var n3 = 0;
		// n3 = n1 + n2 等出来的
		for(var i=3; i<= 9; i++){
			// 第一轮求出n3 
			n3 = n1 + n2;
			// n1等于1 
			n1 = n2;
			//  n2 是 2  
			n2 = n3
			// 正好是下一轮的 n1+n2 
		}
		
	看图来操作:n1 正好是1 n2 也是1 n3是n1+n2的结果 
复制代码

封装斐波那契数列 :

function getFei(num){
		var n1 = 1;
		var n2 = 1;
		var n3 = 0;
		for(var i=3; i<=num;i++){
			n3 = n1 + n2;
			n1 = n2;
			n2 = n3;
		}
		return n3;
	}
	console.log(getFei(9));
	
详细解释:
前面两项相加得到第三项
所有我们需要 三个变量 n1 + n2 = n3;
var n1 = 1;
var n2 = 1;
var n3 = 0;

问的是第 n 个 88 个? 循环 i就是几个 循环几次
for(var i= 3; i<=9; i++){
	n3 是 第n个数的数字 多少 
	m3 = n1 + n2;
	 n1 = n2 ;
	 n2 = n3;
}
console.log(9)
复制代码

函数参数和返回值注意事项

function fn(){
		return 555;
	}

	// 函数调用返回函数值 555  函数名+ 括号 调用函数 执行函数 
	console.log(fn());
	// 打印出函数的 本身 函数名 输出的函数本身
	console.log(fn);
	
	
	这里为了arguments 参数 铺垫  请看好
	
	
	
function funn(){

	}
	// 如果函数没有返回值 返回undefined  没有return 
	console.log(funn());
	

	function getSum(x,y,z){
		return x + y + z;
	}

	console.log(getSum(1,2,3)); //6
	console.log(getSum(1,2,3,6));//6
	console.log(getSum(1,2));//NaN  1+ 2 + undefined  = NaN
	// undefined + 任何数值 都是NaN 除了字符串 

	// 疑问? 用户要是想输入多少是多少怎么办呢? 使用arguments 的使用
复制代码

疑问? 用户要是想输入多少是多少怎么办呢? 使用arguments 的使用

arguments 的使用 js中arguments 对象是比较特别的一个对象,实际上是当前函数的内置属性,也就是伙食所有函数都内置了一个 arguments对象 arguments 对象中存储了传递的所有的实参,arguments是一个伪数组

arguments 对象中存储了传递的所有的实参

function getSum()	{
		// 可以接受 传递过来的所有的 实参 
		// arguments 是一个伪数组 
		console.log(arguments);
		// 存储形式 伪数组
		// 遍历数组 可以把值取出来 
	}
	 getSum(1,2,3,1,2,3);
	 
	 
 案例: 可以求任意数值的和 
        function getSum(){
    			var sum = 0;
    			for(var i=0; i<arguments.length;i++){
    				sum += arguments[i];
    			}
    			return sum;
    		}
    		console.log(getSum(1,2,3));
    		
    		
案例:求任意数的最大值

    function gemMax(){
		var max = arguments[0];
		console.log(max);//1
		for(var i=0;i<arguments.length; i++){
			if(max < arguments[i]){
				max = arguments[i];
			}
		}
		return max;
	}

	console.log(gemMax(1,2,3,4,5,));
复制代码

函数的定义撒三种方式

定义函数的3中方式 

1、声明函数 命名函数
function fn(){

}
fn();
答:实际工作使用多



2、函数表达式 匿名函数
var fun = function(){};
答:Dom操作的时候使用较多 

3、自执行 函数 
答:匿名函数除了 作为参数传递外,也可以作为启动函数,定以后立即执行,为了防止变量污染
匿名 函数自执行函数,最大的好处,就是防止命名冲突 后面会讲 

函数不调用不执行,但是自执行函数自己调用自己
	(function (){

	}) ();
复制代码

函数作为参数使用

	解答:函数可以接受任何类型的数据作为参数,数值,字符甚至是函数类型
	
var fn = function(){
		console.log('这里是一个函数');
	}

	// 声明
	function fun(x){
		console.log(x);
		x();
	}

	// 调用
	fun(fn);
复制代码

函数 可以作为返回值

/*
		function fn(){} //声明函数
		console.log(fn); //输出整个函数 代码
		console.log(fn()) //fn()调用函数 执行函数 
	

	function fn(){
		retrun  666;
	}
	console.log(fn(666)); //返回值 666 
*/

function fn(){

	//返回的是一个函数 
	return function (){
		console.log('返回这里的函数');
	}
}
// console.log(fn());  function (){console.log('返回这里的函数')};

var ff = fn(); //function (){console.log('返回这里的函数')};
ff();

//console.log(ff); //function (){console.log('返回这里的函数')};
复制代码

作用域

答: 作用域: 变量可以起作用的范围

全局变量和局部变量
		全局作用域 
			供所有代码执行的环境整个Script 标签内部 或者一个独立的js 文件中 
		局部作用域
			在调用函数的时候 会形参一个执行函数内代码的新环境
		全局变量
			在全局作用域下声明的变量叫做全局变量
			全局变量在代码任何位置都可以使用
		局部变量
			在局部作用域下声明的变量叫做局部变量
			局部变量只能在该函数内部使用


//全局作用域   
		//num 就是一个全局 变量 
		var num = 10;
		console.log(num);


		//在function 里面写的是 局部作用域 

		function fun(){
			//str 在 局部内写的是局部变量 
			var str = '';
			//全局变量可以全局使用 
			console.log(num);
		}
		fun()//进行调用
		console.log(str);
		
		
注意 : 函数的形参实际上就是局部变量

局部变量当其所在的代码块被执行时候,会被初始化,当代码块运行结束后,就被销毁了,节省内存空间

全局变量因为任何一个地方都可以使用,只有在浏览器关闭才会销毁,比较占内存
复制代码

作用域链:

        只要是代码,就至少有一个作用域
	写在函数外部的就全局作用域
	写在函数内部的就是局部作用域
	如果函数中还有函数,那么在这个作用域中就又诞生一个作用域
	根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
	
练习题:

function f1(){
	function f2(){

	}
}

	var num = 123;

	function f3(){
		function f4(){

		}
	}
	//  解答: f1 和 num  f3 是属于 零级链 就是最牛的那个 相当于盘古
	
案例:
    function f1(){
		var num = 123;
		function f2(){
			console.log(num);
		}
		f2();
	}
	var num = 456;
	f1();


	// 案例
	function f1(){
		// var num = 123;
		function f2(){
			console.log(num);
		}
		f2();
	}
	// var num = 456;
	var num;
	f1();

	// 解答: 零级链 f1 和num 是零级链
	// f1里面的 num  和 f2 是一级链 
	// console.log(num) 是 二级链
	// 假设如果 我们一级链 里面没有找到 123
	就会继续冒泡向上查找 找到  456 如果还没有就会undefined 
	
	
练习题: 答案 留在 评论 写:作用域练习题1与2的答案即可。

var  a = 1;
function f1(){
	var a = 2;
	var b = '2b';
	function f2(){
		var a = 3;
		function f3(){
			var a = 4; 
			console.log(a); //a 的值 4
			console.log(b);  //b 的值 '2b';
		}
		f3();
	}
	f2()
}
f1();

练习题2:

var  a = 1;
function f1(){
	var a = 2;
	var b = '2b';
	function f2(){
		var a = 3;
		function f3(){
			var a = 4; 
			console.log(a); //a 的值 4
			console.log(b);  //b 的值 '2b';
		}
	}
}
复制代码

预解析 重要

	/*
		// console.log(num);  //打印出什么   num is not defined  未定义 
		var num ;
		console.log(num); // undefined  声明变量未给值 

		var num = 10;
		console.log(num)  //输出 10 
	

	console.log(num);  // 请问 预解析  这里输出是undefined 
	var num = 10;

	

	fun(); //函数调用把下面的注释了,在上面输出你会发现什么 下面也会打印出来 

	function fun(){
		console.log('人啊不能偷懒');

	}

	//fun(); 函数调用   

	*/
    
    js 解析器 就是js 引擎 
    
	解答:javascript代码是由浏览器中的js 解析器来执行的,js解析器在运行js代码的时候,分为两步预解析和代码执行 
	为什么学习预解析?
		答:学习了预解析能够让我们知道为什么在变量声明之前访问变量,值是undefined 为什么 在函数声明之前就可以调用函数 
	预解析过程:
		1、js解析器会在全局环境下查找 var function 关键字,变量只声明不赋值,函数声明不调用
		2、预解析只发生在当前作用域下
	预解析也叫做变量,函数提升 
		1、变量提升:定义变量的时候,变量的声明会被提升到当前作用域的最上面啊,变量的赋值不会提升
		2、函数提升:js解析器首先会把当前作用的函数声明提前到整个作用域的最前面
		优先等级:变量名和函数名相同,有限执行函数  重点 
	执行过程:
		变量赋值,函数调用,表达式运算等等
		
上面题讲解:
    console.log(num);
    var num = 10;
   解答: 这里为什么 会打印出undefined 是因为 变量提升,变成了
   var num;
   console.log(num);
   num = 10; 变量的赋值不会提升也就说没有把10赋值给num 声明变量未给值 
上面题讲解:
    	fn();
	function fn(){

	}
	// 为什么 这么写没问题呢?
	// 因为js 预解析 会把我们函数 提升回来 请看
	function fn(){
			// 预解析的功劳 提升回来了,但是变量的声明会被提前,但是值并不会
			// 所以这里就变成了声明变量未给值 so undefined 了 函数是整体的函数声明所以提前了 
	}
	fn();

预解析练习题:
   到时候把答案 写在 留言区吧
        格式:  预解析练习题- 1- 答案
   

题目1、
	        alert(a);
		alert(fn);

		var a  =1;
		function fn(){
			return false;
		}
		
题目2、
         alert(a);

	var a = 1;

	alert(a);
	function a(){
		return false;
	}
解答提示:变量名 和函数名 相同的情况 

题目3、
    var num = 10;
	fun();
	function fun(){
		console.log(num);
		var num = 20;

	}
题目4、
    	var num  = 10;
	fn();
	function fn(){
		console.log(num);
		var num = 20;
		console.log(num);
	}
题目5、
    var a = 10;
	f1();
	function f1(){
		var b = 20;
		console.log(a);
		console.log(b);
		var a = '123';
	}
复制代码

全局变量的特殊形式

 var num =10; //全局变量 
 function fun (){
 	var n = 20; //局部变量 
 	str = 'jack'; //str 放在局部作用域中,全局变量的特殊形式,在局部作用域内声明,但是没写var 当全局变量看 
 	
 }
 fun();  //记着调用 
 console.log(str);
复制代码

题目6、

f1()
console.log(c)
console.log(b)
console.log(a) 

function f1(){
	var a = b = c = 9;
	console.log(a);
	console.log(b);
	console.log(c);
}
复制代码

问答:

问答: 
	1、函数形参和实参个数 可以不匹配 
		答:可以不匹配,但是没什么用
	2、arguments  参数什么时候用
		答:我们不知道接收多少参数的时候用arguments,存储方式和数组 一样 被称为伪数组
	3、定义函数有那2种方式
		答: 函数表达式var a = function(){} 和函数 声明  function fn(){}
	4、js 变量安卓作用域,分为哪两种变量 
		答:全局变量 和局部变量 ,局部变量外面不能用,在局部内没有使用var 的是全局变量 
	5、js 解释器 运行js 分为 那两步
		答:预解析 和代码执行 ,先把 变量 和函数 提升 然后开始运行, 预解析 提升到当前作用域,什么叫做当前作用域就是就是函数内部的 提升到函数内部 
复制代码

转载于:https://juejin.im/post/5c661628e51d45175b4a7f6a

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值