JavaScript第五天

函数的复习

函数:function语句的集合,就是将多个语句封装到一起。

函数的执行,要会自己遍历,遇见fn()执行语句,就要移交控制权。函数执行完毕之后,控制权又移交回来了。

函数声明头的提升,程序一开始就会有一个预解析的过程,程序会通看全部代码,把所有的函数名字都放到开头预习一下,程序自己知道了,页面上有这个函数定义。但是,函数表达式是不能预解析的。

//函数声明头的提升
fn();		//正常会弹窗,把调用写在前面,因为函数声明头会预解析。
fn2();		//报错。函数表达式是不能预解析的
function fn(){
   alert("我是函数");
}

//函数表达式是不能预解析的
var fn2 = function(){
   alert("我是函数2");
}

函数优先 : 如果同一个标识符,在程序中又是变量的名字,又是函数的名字,解析器会把标识符给函数。

var a = 1;
function a(){
	alert("我是函数");
}		
a();
//如果这样书写程序会报错

因为:在执行var a = 1之前,函数已经把function a()预解析了,程序就已经知道页面上有一个函数叫做a。但是开始执行程序之后,定义了一个变量a,所以标识符a,就又变成变量了。遇见function定义,程序会无视,因为已经预解析了。直到a()运行的时候,a就是变量,无法运行,报错。

函数表达式是无法进行函数预解析的会按照变量的方式进行解析

a();
var a = 1;
var a = function(){
	alert("我是函数");
}

函数表达式是不会预解析的,所以预解析的就是变量a的定义,就是undefined,undefined是无法执行的。

变量预解析和函数预解析是不一样的,函数预解析会把整个函数体拿出来使用,但是变量只是把变量名拿出来了

alert(a);//只会弹出undefined因为只是把变量名提前解析了,内容并没有
var a = "张贺";

作用域

一个变量如果定义在了一个function里面,那么这个变量就是一个局部变量,只在这个function里面有定义。出了这个function,就如同没有定义过一样。

	<script type="text/javascript">
		function fn(){
			var a = 1;	//定义在一个函数里面的变量,局部变量,只有在函数里面有定义
			console.log("我是函数里面的语句,我认识a值为" + a);
		}

		fn();
	console.log("我是函数外面的语句,我不认识a" + a);
//这个时候函数外的a是无法输出的,因为a变量是一个局部变量
	</script>

总结

  • 在function里面的变量,叫做局部变量,只在function里面有定义,出了function是没有定义的。

  • 定义在全局范围内的,没写在任何function里面的,叫做全局变量,都可以用

多层嵌套,如果有同名的变量,那么就会发生“遮蔽效应”

var a = 1;		//全局变量
function fn(){
var a = 5;         //就把外层的a给遮蔽了,这函数内部看不见外层的a了。
console.log(a);	//输出5,变量在当前作用域寻找,找到了a的定义值为5
}
fn();
console.log(a);  //输出1,变量在当前作用域寻找,找到了a的定义值为1

作用域链:一个变量在使用的时候得几呢?就会在当前层去寻找它的定义,找不到,找上一层function,直到找到全局变量,如果全局也没有,就报错。

在js中如果不写var默认就是全局变量

//就默认在这里var a;
function fn(){
	a = 1;		//这个a第一次赋值的时候,并没有var过,
				//所以就自动的在全局的范围帮你var了一次
}
fn();
console.log(a);

告诉我们一个道理,变量要老老实实写var。

函数的参数会默认成为这个函数的局部变量

全局变量的作用

功能1:通信,共同操作同一个变量

var num = 0;
function add(){
	num++;
}
function remove(){
	num--;
}

功能2:累加,重复调用函数的时候,不会重置

var num = 0;
function baoshu(){
num++;
console.log(num);
}
baoshu();	//1
baoshu();	//2
baoshu();	//3
//如果num定义在baoshu里面,每次执行函数就会把num重置为0:

函数也有作用域

function 大
{
	function 小
    {

	}
	小();   //可以运行
}
();   //不能运行,因为小函数定义在了大函数里面,离开大函数没有作用域。

闭包

function outer(){
		var a = 333;
		function inner(){
			console.log(a);
			}
			return inner;	//outer返回了inner的引用
		}

		var inn = outer();	//inn就是inner函数了
		inn();			//执行inn,全局作用域下没有a的定义
						//但是函数闭包,能够把定义函数的时候的作用域一起记忆住
						//能够输出333

这就说明了,inner函数能够持久保存自己定义时的所处环境,并且即使自己在其他的环境被调用的时候,依然可以访问自己定义时所处环境的值。

一个函数可以把它自己内部的语句,和自己声明时所处的作用域一起封装成了一个密闭环境,我们称为“闭包” (Closures)。

function outer()
{
    var a = 222;
    function inner()
    {
      alert(a);  
    }
    return inner;
}
var inn = outer();
inn();

闭包在工作中是一个用来防止产生隐患的事情,而不是加以利用的性质。

因为我们总喜欢在函数定义的环境中运行函数。从来不会把函数往外挪。那为啥学习闭包,防止一些隐患。

闭包的性质

每次重新引用函数的时候,闭包是全新的。

也就是说,闭包每次被拿走从新被使用的时候是全新的

function outer(){
			var count = 0;
			function inner(){
				count++;
				console.log(count);
			}
			return inner;
		}

		var inn1 = outer();
		var inn2 = outer();
		inn1();	//1
		inn1();	//2
		inn1(); //3
		inn1(); //4
		inn2(); //1
		inn2(); //2
		inn1(); //5

无论它在何处被调用,它总是能访问它定义时所处作用域中的全部变量

数组

数组(array)是一个有序的数据集合。说白了,数组就是类型的组合(集合)

var a = [12,34,67,98];

数组里可以存储任何类型的数据,包括函数

function fun()
{
    alert("s");
}
var arr = ["哈哈",fun,12,true,undefined];
console.log(arr[1]());

数组的使用方法

1:length

计算数组的项数

var a = [1,2,3,4,5];
alert(a.length);//这样就会输出5因为数组a里有5
//如果想输出一个数组里的最后一项就可以用length-1
alert(a[(a.length)-1]);

如果使用数组中不存在的下标,就会输出undefined

如果想指定数组只需要写上要指定的下标赋值即可

var a = [1,2,3,4,5];
a[5] = 78;//这样就可以给已经定义的数组赋值了
a[66] = 90;	//还可以跳跃指定赋值
//那么此时其他没有指定的项目就是undefined。

如果跳跃赋值了,这个时候再用length检测,我们设置了下标为66的项,强制拉长了数组;

数组一旦缩小就不能放大,改为0就会清空数组

var a = [22,33,44,55,66];
a.length = 2;
console.log(a);
//那么这个a就会输出[22,33]
a.length = 5;
//这时候再把它还原为原始大小,里面还是会额没有的
a.lenght = 0;
//这时候a这个数组就清空了

变量中存储的引用类型其实是存储的地址

	var a = [11,22,33,44];
	var b = a;
	b[0] = "张贺";
	console.log(a);
//这个时候会发现,更改b的时候,a也会收到影响,这说明b里存储的并不是a,而是a的内存地址
  • 果a里面存储的是基本类型,那么语句b=a就是把a的值赋值一份给b。如果a里面存储的是引用类型,那么b将指向a现在指向的位置,a的值不会赋值一份,a、b指向同一个地方。

数组的常用使用方法

数组的头尾操作

  • push()往数组的某位添加一个或多个元素

    var a = [11,22,33,44];
    a.push(55,66,77);
    console.log(a);
    
  • pop()删除数组的最后一项,一次只能删除一项,无法删除多项,并且能够返回被删除的项

    var a = [11,22,33,44];
    var b = a.pop();//这样就能删除数组的最后一项,并赋值给b
    console.log(a);//输出删除后的a
    console.log(b);//输出被删除的
    
  • unshift()在数组开头添加一个或多个元素,并且能返回值;

    var a = [11,22,33,44];
    var b = a.unshift(99,88);//这样就可以往a数组开头加两个数字
    console.log(a);
    console.log(b);//会输出11
    

数组的合并与拆分

  • concat()把使用它的数组和括号里的数组合并返回

    var a = [11,22,33,44],b = [55,66,77];
    console.log(a,b);
    a = a.concat(b);//把b的内容和a的内容相加赋值给a
    console.log(a);
    

    concat()的参数非常灵活,可以是数组变量、数组字面量、散的值也行:

    var arr1 = ["东","西","南","北"];
    var arr2 = ["一条","二条"];
    arr1 = arr1.concat(arr2,["一筒","八条"],"幺鸡");
    console.log(arr1);
    
  • slice(起始下标,结束下标),截取起始下标到结束下标中间的内容,包括起始下标不包括结束下标,并返回新值,原值不变

    var a = [11,22,33,44,55,66,77,88];
    var b = a.slice(3,5);
    console.log(b);//返回结果是33,44
    

    如果只写开头

    var a = [11,22,33,44,55,66,77,88];
    var b = a.slice(3);
    console.log(b);//结果会从下标为3的地方截取到最后
    

    结果为倒数

    倒数时,下标从-1开始

    var a = [11,22,33,44,55,66,77,88];
    var b = a.slice(-6,-4);
    console.log(b);
    //从倒数第4,截取到倒数第2,不包括倒数第2
    
  • spice——插入,删除,替换

    //用于替换
    var arr = [a,b,c,d,e];
    arr.splice(3,2,"zh","he","ya");//(括号里前两项写从下标为几的开始替换,第二个写替换几位,可以替换也可以替换增加)
    console.log(arr);
    //用于删除
    var arr = [a,b,c,d,e];
    arr.splice(2);//只写了一个下标,这样数组就会从下标,往后全部删掉
    console.log(arr);
    //用于插入
    var arr = ["a","b","c","d","e"];
    arr.splice(2,0,"zhanghe");
    console.log(arr);
    
  • reverse——数组倒置

    var arr = [1,2,3,4,5,6];
    arr.reverse;
    console.log(arr);
    
  • sort——数组排序

    arr.sort(function(a,b){
    //如果a要放在b前面,那么返回负数
    //如果a要放在b后面,那么返回正数
    //如果a和b不区分大小,那么返回0
    if(a < b){
    	return -1;
    }else if(a > b){
    	return 1;
    }else if(a == b){
    	return 0;
    }
    	});
    
    //数组排序
    var arr = [];
    var a;
    while (a = parseFloat(prompt()))
    {
        arr.unshift(a);
    }
    arr.sort(function(a,b){
        if (a>b)
        {
            return 1;
        }
        else if(b>a)
        {
            return -1;
        }
        else
        {
            return 0;
        }
    });
    alert(arr);
    
  • join——转为字符串

    //join语法
    var 变量 = join(分隔符);
    
    var arr = [1,2,3,4,5];
    arr = arr.join("-");
    alert(arr);
    //1-2-3-4-5
    

字符串的常用使用方法

  • length测试字符串的长度

    var a = "张贺";
    var b = a.length;
    console.log(b);//输出2
    
  • charAt() 返回在指定位置的字符

    var a = "张贺";
    var b = a.charAt(0);
    console.log(b);//输出张,和数组的下标类似
    
  • concat() 连接字符串

    var a = "张",b = "贺";
    a = a.concat(b);
    console.log(a);
    
  • indexOf() 检索字符串

    console.log("我爱你i love you".indexOf("爱"));
    //输出1,输出前面字符串中的下标数字
    
  • replace() 替换

    "abcdefgaa".replace("a","0");    // "0bcdefgaa"
    //把字符串中的a替换成了0,只替换了这一个
    
  • slice() 提取

    "我爱你亲爱的祖国的人民币".slice(-3,-1)   //"人民"
    
  • split() 把字符串→数组, 从什么地方拆分, 就是参数

    "我爱你亲爱的祖国的人民币".split("的"); 
    //输出——["我爱你亲爱", "祖国", "人民币"],遇到的就拆分了
    
  • substr() 截取子串

    "abcdefghijklmn".substr(3,5);
    //从下标为3的地方开始,取5个字符
    //defgh
    
  • substring() 截取子串,substr和substring不一样:

    "我爱你亲爱的祖国的人民币".substring(6,8)
    //输出祖国,从下标为6的地方截取到下标为8的地方,不包括8
    
  • toLowerCase()、toUpperCase();

    转换为大小写

    "zhanghe".toUpperCase();
    //"ZHANGHE"转换为大写
    "ZHANGHE".toLowerCase()
    //"zhanghe"转换为小写
    
posted @ 2019-12-16 20:42  张贺zhanghe  阅读(68)  评论(0)    收藏  举报