震惊!js基础竟是......(一)

161 阅读15分钟

一、

1、JavaScript概述:

简称JS,是运行在【javascript解释器 或者 特定引擎中】的【解释型】【弱类型】【面向对象】脚本语言.
    

1、javascript解释器:

        1、浏览器自带js解释器.
        2、独立安装一个js解释器 - node.js时

2、类型

    编译型:运行程序之前,需要检查语法是否正确,如果不正确直接不允许运行,比如:java、cc++c# - 更加严格
解释器:运行程序之前,不要检查语法是否正确,直接运行,碰到错误就会停止运行,比如:javascript、php、node.js... - 更自由

3、js特点:

        1、代码可用任何文本编辑器编写:vscode hbuilder 记事本...
        2、解释型语言,无需编译
        3、弱类型语言:不需要进行规定,你想放什么就放什么变量的数据类型是由值来决定的
        4、强类型语言:先要规定你的变量要保存什么数据类型,才能往里面放入什么东西,比如java - 更严格,变量的数据是由 数据类型 来决定的 你能放入的值是什么

4、面向对象语言:

    程序员眼看任何东西都是一个对象:有了一句话叫做 万物皆对象

5、js作用:

	1、客户端的数据的计算:购物车
	2、表单的数据验证:(手机号、身份证、邮箱、密码)
	3、提供了事件(点击、鼠标移入移除、键盘...)
	4、网页中一切css做不了的特效,都由js完成
	5、和服务器端进行交互 ajax
            

2、javascript使用:

1、使用方式:2个
	1、在HTML页面写上一个标签:
		<script>
			js代码
		</script>

	2、创建一个xx.js文件,在里面书写js代码,最后在HTML页面引入
		<script src="xx.js文件路径">//此处不再支持书写代码了</script>

2、JS的调试语句:

    代码运行期间,如果碰到错误,会报错,但是后续代码就不会执行了,甚至如果只是逻辑错误不是语法错误,那并不会报错,我们需要一个方式去帮助我们找到错误何在
       *1、在控制台输出日志:console.log(想要输出的东西);//打桩输出,疯狂打桩
	2、在页面上进行输出:document.write(想要输出的东西); - 如果绑定上了事件,会将页面上所有的内容全都替换掉
	3、弹出框显示:alert(想要输出的东西); - 会卡主整个页面,必须关闭后用户才能看到HTML和CSS

3、js的语法规范:

    是严格要求区分大小写的,不能乱写

4、JS注释:

    作用:1、*提示程序员  2、玩
	单行注释://
	多行注释:/****/

5、*变量:

   硬盘:保存文件、数据(外部存储器)
   CPU:中央处理器:计算 暗黑3
   内存:是【临时保存】程序在运行过程中,所需要用到的数据 - 本质来说我们的一个变量也是一个内存
	 内存空间:保存数据的一个地方
	 内存地址:内存空间的一个门牌号:大概长这样:0x00003021000310321,所以一般来说可以再起一个别名(变量名)

   变量:值是可以改变的
	 特殊:
		1、=:赋值符号,将=右边的数据放到=左边的变量名之中
		2、如果只声明/创建/定义了,没有赋值的话,默认值为undefined(没有任何用处),记得一定要赋值。
		3、取变量名不能随意,尽量的见名知意
			不能以数字开头
		4、如果创建多个变量,中间的var可以省略,中间的;换为,,最后一个依然是;结束
		5、面试题:如果是一个未声明的变量直接使用,会报错
			   如果是一个声明过的变量但是未赋值,会undefined
		6、name变量名是一个关键字,里面只能放入字符串,哪怕你放的不是字符串,也会悄悄变成一个字符串

6、常量:

    一旦初始化后(第一次赋值),值不允许被修改
	 语法:const 常量名=值; - 和变量除了关键字不同,没有别的不同了

7、*算术运算符:+ - * / %

	其实前四个运算符和小时候一模一样
	但是特殊:
	    1、%:取余,俗称模,两个数相除,但是不取商,而取余数
			5%2 ==> 1
			2%5 ==> 2
		  作用:1、*判断奇偶性
				num%2;//结果为0说明是一个偶数,结果为1说明是一个奇数
			2、获取某个数字的最后n位
				1234%10 ==> 4
		  		1234%100 ==> 34
				1234%1000 ==> 234
				
	    2、***隐式转换:悄悄的转换,数据类型会发生变化,我们程序员看不见
		  常理来说只有数字才能参与算术运算,但是其实字符串也可以,一定要切忌以下几句话
		  *****默认运算符左右两边都会悄悄的变成一个数字,在运算
			 特殊:1、+运算,只要碰上一个字符串,则都变为字符串,+运算也不再+运算,变成了拼接字符串操作
			       2、-*/%运算,有字符串也可以转为数字,但是必须是纯数字组成的字符串才可以,只要包含了非数字字符,结果则为NaN(垃圾)
					NaN:Not a Number:不是一个数字,但是确实是数字类型 - 不是一个有效数字,不在三界之中
						NaN参与任何算术运算结果仍为NaN
						NaN参与任何比较运算结果都为false
					以后不希望见到NaN和undefined
                                            

8、*JS中数据类型:

	1、原始/基本/值类型:51String - 字符串,取值有无数个,必须写"" 或者 ''
		2Number - 数字,取值有无数个,直接写个数字就行
		3Boolean - 布尔,取值只有两个,truefalse,多半都是用于判断比较
		4Undefined - 取值只有一个默认值undefined,没有任何用处 - 祖师爷犯的一个错误
		5Null - 空,取值只有一个null,作用:释放变量、内存,节约内存空间
	2、引用/对象类型:11个,每个对象都有很多的属性和方法等待我们去学习

扩展:

  1、弹出一个用户输入框:var user=prompt("提示文字","默认值");
  2、分支结构:根据条件的不同,选择一部分代码执行操作
	1、一个条件 一件事,满足就做,不满足就不做
		if(条件){
			操作
		}
	
	2、一个条件 两件事,满足就做第一件,不满足就做第二件
		if(条件){
			操作
		}else{
			默认操作;
		}

	3、多个条件多件事,满足谁就做谁
		if(条件1){
			操作1
		}else if(条件2){
			操作2
		}else if(条件3){
			操作3
		}else{
			默认操作;
		}
	
	注意:1、else if你想写几句就写几句
	      2、最后的else其实也可以省略,但是如果条件都不满足的话则什么不会执行 - 不推荐,什么都不执行相当于我们的分支白写了
	      3、分支结构只要满足一个就不可能再走另一条路了

二、

1、***数据类型转换:

javascript是弱类型语言,数据类型都是由数据来决定的

对于不同数据类型的运算时,数据类型会进行转换:
	number + number = number
	number + string = string

如果你喜欢查看数据类型:typeof(需要检查的人);

1、算术运算隐式转换:

        其他运算也有
	自动转换,悄悄的,我们程序猿是看不见的
	其实只要是算术运算就一定带有隐式转换,默认会将左右两边转为数字,再运算
	特殊:1、+运算,如果碰到了一个字符串,那么左右两边都会悄悄转为字符串,再拼接
	      2、-*/%,就算是字符串也可以转为数字,但是不需要是纯数字组成的才可以,只要包含了非数字字符,则为NaN
	      3、某的人转为数字的结果
			true->1
			false->0
			undefined->NaN
			null->0
			"100"->100
			"10a0"->NaN
	      4、NaN:Not a Number,不是一个数字,但是确实是数字类型,理解为是一个无效的数字
			缺点:1、NaN参与任何算术运算结果仍为NaN
			      2、NaN参与比较运算结果都为false
				 问题:我们没有办法使用普通的比较运算来判断x是不是NaN
				 解决:个人更爱反用:
					!isNaN(x) - 判断x是不是一个有效数字
					true->说明是一个有效数字
					false->说明是一个NaN

2、强制/显式转换:

   隐式转换的结果可能不是我们想要的,我们程序员可以手动调用某些方法,进行数据类型的转换后,再运算
   1、转为字符串:
	语法:var str=x.toString();//x不能是undefined和null,因为undefined和null不能使用.操作
	此方法不重要,页面上获取来的所有的数据默认都是字符串

   2、*转数字:3个方法
	*1var num=parseInt(str/num);  parse->解析 Int->整型/整数
	   原理:从左向右依次读取每个字符,进行转换,碰到非数字字符就停止,而且不认识小数点,如果一开始就碰到了不认识的字符,结果为NaN
		console.log(parseInt(35.5));//35
		console.log(parseInt("35hello5"));//35
		console.log(parseInt("hello35"));//NaN
		console.log(parseInt("35px")+100+"px");//35
		console.log(parseInt(布尔、undefinednull));//NaN

	*2var num=parseFloat(str);  parse->解析 Float->浮点数/小数
	   原理:几乎和parseInt一模一样,认识小数点
		console.log(parseFloat("35.5"));//35.5
		console.log(parseFloat("35.5px"));//35.5
		console.log(parseFloat("35.5.5"));//35.5 - 数字只有一个小数点,第二小数点就是不认识的字符
		console.log(parseFloat(".55"));//0.55
		console.log(parseFloat("px35.5px"));//NaN
		console.log(parseFloat(true));//NaN

		以上两个都可以去掉字符串的单位

	3Number(x);//x是万能的,任何人都可以转为数字
		     //垃圾,因为此方法完全就是隐式转换,也不能转带有非数字字符的字符串,还不如对着x *1 /1 -0,绝对不要手动使用

	总结:1、只要页面上带有单位的数字,我们都可以用parseXXX来去掉单位变为数字
	      2Number何时都不用

2、*****函数:

函数是第一等公民的地位

1、什么是函数:

    也称为方法,需要【预定义】(提前创建好)后,可以【反复使用】的【代码段】(里面可以放若干代码)
	

2、创建函数并且调用函数

	第一步:
	创建:function 函数名(){
			若干代码段
	      }
	第二步:
	调用:2种方式
	1、直接在js里面写 函数名(); 程序员写几次就会执行几次

	2、绑定在页面的元素上,让用户来触发,用户触发一次就会执行一次 - 提升用户体验感/多了交互感
		<elem onclick="函数名();"></elem>

3、以后何时要使用函数呢?

	1、打开页面不希望立刻执行
	2、希望用户/程序员来触发
	3、希望能够被反复执行
	4、本身就是一段独立的功能体:暂时理解为我们的每一个作业就是一个独立的功能体
	5、以后要尽量的将每个功能封装为一个函数,函数是第一等公民的地位,而且函数中的变量会自动释放

4、带有参数的函数

	1、创建带参数的函数:
		形参:就是一个变量名,只不过这里的变量名不需要var,并没有保存真正的值,形式参数,简称形参
		function 函数名(形参,...){
			函数体;
		}

	2、调用带参数的函数:
		实参:实际参数,这个变量名所保存的值
		函数名(实参,...)

	一个函数可以执行相似的操作

	比如:实现任意两个数相加:
		function add(a,b){
			console.log(a+b);
		}
		add(1,2);
		add(3,4);
		add(5,6);
	注意:带参数的函数,在调用时,传入的实参的顺序和个数都要一一的和形参对应上

	总结:
	  1、如果你的函数体是固定不变的,则不需要使用带参数的函数
	  2、如果你的函数体希望根据传入的实参的不同,做的事儿也略微不同,需要使用带参数的函数

3、***分支结构

1、代码中流程控制语句:3种

1、顺序结构:
   默认结构,代码从上向下一步一步执行的

2、分支/选择结构:
   根据条件,选择一部分代码去执行

3、循环结构:
   根据条件,判断你是否需要再一次重复的执行某一些代码

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

作用:比较判断/条件中出现
结果:以上六个运算符,结果一定是一个布尔值
其实比较运算符也具有隐式转换,但是我不给你说,大部分情况下依然会转为数字在比较大小

3、if结构:

1、一个条件一件事,满足就做不满足就不做
	if(条件){
		操作
	}

2、一个条件2件事,满足就做1不满足2
	if(条件){
		1
	}else{
		2
	}

3、多个条件多件事,满足谁就做谁
	if(条件1){
		1
	}else if(条件2){
		2
	}else{
		3
	}

扩展:

逻辑运算符:&&(与、并且) ||或 !非
&&:只有全部条件都满足,最后结果才为true
    只要有一个条件为false,结果就为false

||:只有全部条件都不满足,最后结果才为false
    只要有一个条件为true,结果就为true

 !:颠倒布尔值
	!true -> false
	!false -> true
	!!!true -> false

三、

1、****循环结构:

1、问题:

   在控制台打印输出10000句hello world
console.log("1hello world")
...
console.log("10000hello world")

2、什么是循环:【反复执行相同 或 相似的操作】

生活中:
	1、吃饭
	2、睡觉
	3、学习
	4、上班
	5、活着

循环三要素:
	1、循环条件:开始、结束:重复执行的次数
	2、循环体:循环的操作:要干什么
	3、循环变量,并且 变量需要不断的变化

3、while循环:

语法:
var 循环变量=几;
while(循环条件){
	循环体;
	循环变量变化一下;
}

执行原理:先判断循环条件,如果条件为真,则执行【一次】循环体
	  然后再判断循环条件,如果条件为真,则执行再【一次】循环体
	  ...
	  直到条件为假,循环才会结束
注意:循环是一次一次执行的 - 并不是同事执行的,只不过计算机的CPU计算速度比较快

死循环:永远不会结束的循环 - 保存死循环也是可以退出循环
  何时:不确定要执行的具体次数,但往往死循环会搭配上break进行退出
	while(true){
		循环体
	}

循环退出语句:break; - 出现循环之中

     特殊:
   1、死循环:for(;;){循环体} - 两个分号一个不能少

   2、循环变量处其实可以创建多个变量

   3、也支持break

总结:
  1while:一般都不用,何时使用:不确定循环次数的时候
  2for:常用,确定循环次数时

2、*****数组:

1、问题:

   保存1000个人的姓名? - 如果是以下这种写法,我们开辟1000个内存空间
var name1="张三1"
...
var name1000="张三1000"

解决:数组:多个数据/元素组成的一个集合,保存在一个变量中
	    数组中的元素都是按照线性顺序来排列,除了第一个元素,每个元素都有一个唯一的前驱元素
					       除了最后一个元素,每个元素都有一个唯一的后继元素
	    *数组中每个元素都有一个唯一的位置序号,称之为【下标】,用来表示数组中的每一个元素
			下标是从0开始,到最大长度-1

2、创建数组:2种方式:

1、*直接量方式:
	var arr=[];//空数组
	var arr=[数据,数据,...];

2、构造函数方式:此方法还有一个坑,但是我不说
	var arr=new Array();//空数组
	var arr=new Array(数据,数据,...);

3、*访问数组:

1、获取数据
	数组名[下标];

	特殊:1、下标越界,获取到的是一个undefined

2、添加数据
	数组名[下标]=新数据;

	特殊:1、如果下标处已有元素,则为替换
	      2、如果下标越界,会导致你的数组变成一个稀疏数组,中间就会出现很多的undefined,而且下标也不再连续

    结论:数组具有3大不限制:
	1、不限制元素的长度
	2、不限制元素的类型
	3、不限制下标越界 - 但是这个操作并不是好事情,强烈不推荐下标越界

4、*数组对象 - 唯一属性

正是因为我们自己数下标容易数错,提供了一个属性:语法:数组名.length - 获取到数组的长度

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

5、*遍历数组:将数组中的每个元素都取出来 执行 相同 或 相似的操作

 公式:for(var i=0;i<arr.length;i++){
		arr[i];//当前次获取到的元素
       }

四、

1、javascript其实一共由3部分组成:

	1、ECMAScript - 简称ES3/5/6,核心语法 - 内功心法(逻辑部分)
	2、Document Object Model - 简称DOM,文档对象模型 - 外功招式(专门用于操作网页文档HTML+CSS的)
	3、Browser Object Model - 简称BOM,浏览器对象模型 - 外功招式(专门用于操作浏览器的)

2、DOM树:

DOMHTML看做了是一个倒挂的树状结构,但是树根不是你们理解的HTML标签
  *树根:是一个document对象,document对象不需要我们程序员创建,由浏览器的JS解释器创建,一个页面只有一个document
   作用:提供了一些属性和方法,可以让我们程序员去操作整个DOM树(增删改查每一个DOM节点)
   DOM节点:一个标签、文本、属性、元素

3、查找元素:

1、通过HTML的特点去查找元素
1、id查找:var elem=document.getElementById("id值");
   在当前DOM树中,根据元素的id,获取具体的DOM节点
   返回:找到了,返回对应的元素
	 没找到,null
   特殊:1、如果页面上有多个重复的id,只会返回第一个
	 2、此方法找到的是单个元素 - DOM节点是可直接用于做操作的
	 2、此方法你不能使用 - 以后留给后端工程师使用

   *2、标签名查找:var elems=document/已经找到的父元素.getElementsByTagName("标签名");
   在当前DOM树中,根据标签名获取元素们
   返回:找到了,返回一个DOM集合
	 没找到,空数组
   特殊:1、返回的不是一个DOM节点,而是一个DOM集合,是不能直接用来做操作的,要么使用下标拿到某一个,要么使用遍历拿到全部
	 2、不一定非要从树根开始查找元素,也可以写一个你已经找到的某个父元素

   *3、class查找:var elems=document/已经找到的父元素.getElementsByClassName("标签名");
   在当前DOM树中,根据标签名获取元素们
   返回:找到了,返回一个DOM集合
	 没找到,空数组
   特殊:1、返回的不是一个DOM节点,而是一个DOM集合,是不能直接用来做操作的,要么使用下标拿到某一个,要么使用遍历拿到全部
	 2、不一定非要从树根开始查找元素,也可以写一个你已经找到的某个父元素

   2、节点之间的关系进行查找:前提:必须先要找到一个人,才能使用关系
        父:elem.parentNode;//单个元素
        子:elem.children;//集合
        第一个儿子:elem.firstElementChild;//单个元素
        最后一个儿子:elem.lastElementChild;//单个元素
        前一个兄弟:elem.previousElementSibling;//单个元素
        后一个兄弟:elem.nextElementSibling;//单个元素

4、操作元素:

<标签名 属性名="属性值" style="样式">内容</标签名>
1、内容:
  *1、innerHTML属性:获取 或 设置 某个元素的内容,并且可以识别标签
	获取内容:elem.innerHTML;
	设置内容:elem.innerHTML="新内容";

   2、innerText属性:获取 或 设置 某个元素的文本,不能可以识别标签
	获取内容:elem.innerText;
	设置内容:elem.innerText="新内容";

   以上两个属性,是为双标签准备的

   3、value属性:专门为单标签(input)操作内容准备的
	获取内容:input.value;
	设置内容:input.value="新内容";

2、属性:什么是属性:HTML属性:id、class、title、alt、style、type、href...只要是放在HTML标签上的都是一个属性
	1、获取属性值:elem.getAttribute("属性名");
	2、设置属性值:elem.setAttribute("属性名","属性值");

	以上两个方法有点繁琐 - 但是无敌的
	能够简化:
		1、获取:elem.属性名;
		2、设置:elem.属性名="属性值";

		缺陷:1、不能操作自定义属性,只能操作标准属性
		      2、class在ES6升级为了一个关键字,所以想要写class换为了className

3、样式:
   1、css定义的方式:3种
	1、内联样式 - 二阶段
	2、内部样式表
	3、外部样式表 - 最适合写样式的时候使用此方法

   2、JS操作内联样式的好处:
	1、优先级最高,写的JS样式必定生效
	2、一次只会操作一个元素,不会牵一发动全身

   3、语法:
	获取:elem.style.css属性名;
	设置:elem.style.css属性名="css属性值";

	特殊:1、css属性名,要把有横线地方,换成小驼峰命名法
	      2、获取的时候,代老湿只交了大家获取内联样式,不能获取样式表中的样式

        4、元素绑定事件:
            单个元素:elem.onclick=function(){
                          操作;
		this->单个元素绑定事件,this->elem绑定事件的这个元素
	  }

多个元素:for(var i=0;i<elems.length;i++){
		elems[i].onclick=function(){
				操作
				this->多个元素绑定事件,this->当前触发事件的元素
		}
	  }

***总结:

   1、一切的获取都是为了判断
   2、一切的设置都是为了修改
   3、千万不要对着一个集合做操作,要么遍历拿全部,要么下标拿一个