前端学习JS第二周

131 阅读9分钟

第二周

第一天

数据类型转换

强制转换

1.转字符串:2种

		1、x.toString();//undefined和null不能使用,不能用.调用方法
		2String(x);//万能的,但是没什么用,千万不要手动使用,完全相当于隐式转换,还不如+""
		都没啥用 - 页面上的一切数据都是字符串 

2.转数字:

1、*parseInt(str/num) - 专门用于将字符串转为整数的 执行原理:从左向右依次读取每个字符,碰到非数字字符则停止,一来就不认识则为NaN

		   parseInt("35px");//35;
		   parseInt("3.5px");//3;
		   parseInt("px3.5");//NaN;
		   parseInt(true);//NaN;

		2、*parseFloat(str); - 专门用于将字符串转为浮点数的
		   执行原理:几乎和parseInt一致,但是认识第一个小数点
		   parseInt("3.5px");//3.5;

		3Number(x);//万能的,但是没什么用,千万不要手动使用,完全相当于隐式转换

3.转布尔: Boolean(x);//万能的,但是没什么用,千万不要手动使用,完全相当于隐式转换。

		*哪些东西会转为false6个:0,"",undefined,null,NaN,false,其余的全部都为true
		注意:一定要记住哪些人会为false,有用!在【循环或分支的条件判断中】,不管你写的是什么,都会悄悄的隐式转为布尔值
		if(Boolean(条件)){

		}

		while(Boolean(循环条件)){

		}

隐式转换:都出现在运算符之中

2、运算符和表达式:

1、*算术运算:+ - * / %

   隐式转换:默认,转为数字,再运算
       特殊:1+运算,只要碰上一个字符串,则变为拼接
	     2- * / %,纯数字组成的字符串也可以转为数字,但是非纯数字字符串则为NaN
            NaN参与任何算术运算结果都为NaN

2、*比较运算:> < >= <= == != === !==

        结果:布尔值
        隐式转换:默认,左右两边都会悄悄的转换数字,再比较
	特殊:1、如果左右【两边】参与比较的都是字符串,则是按位PK每个字符的十六进制的unicode号(十进制ascii码);
			不需要记忆,但是要知道常识:
				0-9<A-Z<a-z<汉字
				汉字:记不了,太多了,20000+个以上,汉字一定比数字、英文大
				百度搜索:中文字符集 Unicode 编码范围
				汉字的第一个字:一(unicode:4e00ASCII码:19968);
				汉字的最后一个字:龥(unicode:9fa5,ASCII码:40869);
				了解着玩的常识

	      2NaN参与任何比较运算结果都为false,甚至不认识自己,解决:
			!isNaN(x); true->有效数字 false->NaN

	      3undefined==null;
		 问题:==区分不开undefinednull,怎么才能区分开?
		 全等:===,要求值和数据类型都要相同,换句话说,就是不再带有隐式转换的比较运算
		      !==,不带有隐式转换的不等比较
                          

3、*逻辑运算符:

	隐式转式:悄悄的都变为布尔值,然后再综合比较
	&&:全部条件都满足,结果为true
	    只要一个条件不满足,则为false
	||:全部条件都不满足,结果为false
	    只要一个条件满足,则为true
	 !:颠倒布尔值

特殊:用法

	短路逻辑:只要前一个条件已经可以得出最后结论,则后续条件不在执行:
		&&短路:如果前一个条件为true,则后一个操作才执行
			如果前一个条件为false,则后一个操作不执行
			简化【简单的】分支:if(条件){操作}
			语法:条件&&(操作);
			举例:曾经:if(total>=500){total*=0.8}
			      现在:total>=500&&(total*=0.8);
			特殊:1、【简单的】->操作只能有一句话
			建议:简单的操作可用&&短路代替,但是操作如果复杂了还是建议使用if结构

		||短路:如果前一个条件为true,则后一个不看
			如果前一个条件为false,则后一个才看
			使用场景:两个值二选一 - 后期做浏览器的兼容性问题的
			e=e||window.event; - 见小案例,bom部分

赋值运算:

       一句话执行了两个操作,先运算,再赋值
	+= -= *= /= %= ++ --;
	何时使用:只要取出变量中的值,在做运算,之后还要在保存回去时,就是用它
	i=i+1;//比较low的写法
	推荐:
	i+=1 或者 i++;
	递增:i++; 每次只能+1
	累加:i+=n; 每次想加几,随便你
	***鄙视题:++分为 ++ii++
		1、单独使用时,没有参与别的表达式,放前放后都一样
		2、如果参与了别的表达式:
		变量中的值其实都会+1
		++i,返回的是递增后的【新值】
		i++,返回的是递增前的【旧值】

、*三目运算:简化了if(){}else if(){}else if(){}else

	语法:
	 1、条件?操作1:默认操作;

	 2、条件1?操作1:条件2?操作2:默认操作;

	问题:1、只能简化简单的分支结构 - 三木操作也只能有一句话,不怕,其实以后你会发现很多if结果中操作恰巧只有一句话
	      2、默认操作是不能省略的 - 哪怕条件都不满足,至少还要做一件事

	总结:
	if(){}			==		&&短路
	if(){}else 		==		三目
	if(){}else if(){}else	==		三目
            

第二天:

自定义Function:

          什么是函数:需要先定义好,可以反复调用的一个代码段
          何时使用:1、不希望打开页面立刻执行 2、以后可以反复的使用 3、希望绑定在页面元素上
          
          
          1、如何使用:
      1、创建:2种
       *1、【声明方式】创建函数:
	function 函数名(形参,...){
		函数体;
		return 返回值;
	}
         2、【直接量方式】创建函数:
	var 函数名=function(形参,...){
		函数体;
		return 返回值;
	}
         2、调用:
	var 接住返回的结果=函数名(实参,...);
	return的本意其实是退出函数,但如果return后面跟着一个数据
	顺便将数据返回到函数作用域的外部,但是return只负责返回,不负责保存
	就算你省略return,默认也会return undefined;
	具体要不要return,全看你需要不需要获得函数的结果
	往往前辈们提供的预定义函数底层都有一句return操作

作用域:2种

     1、全局作用域:全局变量 和 全局函数,特点:在页面的任何位置都可以使用
     2、函数/局部作用域:局部变量 和 局部函数,特点:在【当前函数调用时内部可用】
	导致变量的使用规则:优先使用自己的,自己没有找全局,全局没有就报错
	特殊:缺点:
		1、千万不要在函数中对未声明的变量直接赋值 - 导致全局污染,解决:尽量变量使用前都要记得先var一下
		2、局部可用全局的,但是全局不能用到局部的 - 解决:看上面,搭配上return

3、声明提前:- 鄙视

 在程序正式执行之前
 将var声明的变量(轻)和function【声明的】函数(重)
 都会悄悄的集中定义在当前作用域的顶部
 但是赋值留在原地

 声明方式创建的函数会完整的提前(第一种)
 直接量方式创建的函数不会完整的提前,只有变量部分会提前(第二种)

 何时使用:永远不会自己使用,垃圾干扰我们的判断 - 只会在鄙视中遇到
	只要你遵守以下规则:
		1、变量名和函数名尽量不要重复
		2、先创建后使用
		3、如果鄙视时,遇到先使用后创建,多半都是在考你声明提前,先转换为我们认识的代码,再去判断
                    

第三天

1、循环结构:反复执行 相同 或 相似的操作:

  1while(循环条件){循环体;变量变化;} - 不确定循环次数的时候
2do{循环体;变量变化;}while(循环条件)
鄙视/面试中:whiledo...while的区别
只看第一次:如果第一次大家都满足,两者没有区别
 如果第一次都不满足,while什么都不执行,do...while至少会执行一次
3、***for(循环变量;循环条件;变量的变化){ - 明确次数
	循环体;
   }
4、*循环流程控制语句:退出循环:break;//退出整个循环
			      continue;//退出本次循环,根据需求判断自己还需不需要执行后续的循环

数组的基础

1、基础概念:

	什么是数组:在一个内存(变量)中保存了多个数据的一个集合结构
	何时:只要存储多个相关的数据,都要用数组集中保存
	为什么:一个好的数据结构,可以极大地提升我们程序员的开发效率

2、创建:2种

	1、*直接量:var arr=[值1,...];
	2、构造函数:var arr=new Array(值1,...); - 还有一个坑:var arr2=new Array(5);//创建了一个长度为5的空数组
            

3、访问:数组名[下标]; -- 当前元素

   添加/修改:数组名[下标]=新值;
   特殊:读取元素,下标越界 -- 返回undefined
	 添加元素,下标越界 -- 下标不连续,导致变成一个稀疏数组

4、数组的三大不限制:

	1、不限制长度
	2、不限制类型
	3、不限制下标越界

5、数组唯一的属性:arr.length; 获取到数组的长度

	三个固定套路:
		1、末尾添加:arr[arr.length]=新值;
		2、获取倒数第n个:arr[arr.length-=n]
		3、删除倒数n个:arr.length-=n

6、遍历数组:对数组中的每个元素执行 相同 或 相似的操作:

	for(var i=0;i<arr.length;i++){
		arr[i];//当前元素

7、*如何释放一个引用类型:

         请你看清楚你的这个引用类型的数据有几个变量引用着,每个变量都要释放后,才能真正的释放干净
	建议:我们的代码都要封装到一个函数中,函数中的变量会自动释放
            

8、索引数组:下标都是数字组成的数组

   关联(hash)数组:下标是可以自定义的
   为什么:索引数组的下标无具体的意义,不便于查找
   如何使用:
	1、创建:21、先创建一个空数组:var arr=[];
		2、为数组添加自定义下标并且添加元素值:arr["自定义"]=新值;

	2、访问:arr["自定义"]

	3、强调:hash数组length永久失效,永远为0!
	   遍历hash数组:不能使用for循环,必须使用for in循环 - 专门用于遍历hash数组准备的方式,但是代老湿个人不爱称呼他叫做一个循环
		for(var i in arr){
			arr[i];
		}
	   for in虽然不能定义从哪里开始,到哪里结束,专门用于遍历hash数组的
	   个人推荐:索引数组依然使用for循环,hash数组再用for in

4、hash数组的原理:

		hash算法:将字符串,计算出一个尽量不重复的数字(地址值)
			  字符串内容相同,则计算出的数字也一定是相同的
		添加元素:将自定义下标交给hash算法,得到一个数字(地址值),把我的元素保存到了这个地址值之中
		读取元素:将指定的自定义下标交给hash算法,得到一个和添加时完全相同的数字(地址值),根据地址值找到之前保存的东西

5、js里面一切的东西都是对象:除了undefined和null,【一切对象的底层都是hash数组】