JS基础

67 阅读12分钟

JavaScript概述:

JavaScript简称:JS,是一个运行在[js解释器]中的一个[解释型][弱类型][面向对象]的脚本语言

一、js解释器:1.浏览器都自带js浏览器 2.也可以自己安装js解释器(Node.js)

1.编译型: 在运行程序之前,需要先检查程序是否有报错,如果有报错直接不运行,比如java、c#、c++ ..这些语言比较严格。

2.解释型:在运行程序之前,不需要检查程序是否有报错,直接运行,碰到错误才会停止,比如javaScript、php ...这些相对比较自由一点。

3.弱类型:变量想保存什么数据类型就保存什么数据类型,如:javaScript、php ...

4.强类型:变量想保存什么类型就保存什么类型,但是需要提前声明,由于数据类型决定了能保存什么内容。比如Java ...严格;

二、JavaScript的特点(我们的js都是比较自由的)

1.用任何文本编辑器都可以写代码:HBuilder、VSCode、记事本开发都可以,只要你想,都行。

2.解释型 :在运行程序之前,不需要检查程序是否有报错,直接运行,碰到错误才会停止,比如javaScript、php ...这些相对比较自由一点。

3.弱类型:变量想保存什么数据类型就保存什么数据类型,如:javaScript、php ...

4.面向对象:我们经常用的就是面向对象,万物皆对象 写法: 对象名.属性名; 对象名.属性名();

三、JavaScript怎么使用

1.JS的引入方法有两种:
    内部样式:在已写好的hmtl下+标签(这种方法仅仅用于临时测试)
    <script>
    JS代码用警告框输出:alert(想要输出的内容); - 缺点:会卡主页面,只能看到白板。
    </script>
    
    2.创建一个  文件名.js,在HTML进行引入 (这种用法在---正式开发中---用)
    在HTML文件里面<script src="文件名.js">
    注意:html里面不能写js代码,去创建的js文件里面写
    </script>
2.打桩输出(这里的意思是调试代码,不要怕错)
    这是一种非常重要的找错方式:有31.也是我们多用的输出方式   在控制台输出:console.log(需要输出的内容);
    2.在页面上输出:document.write(想要输出的内容);可以识别标签,
    有缺点:如果有点击事件会触发document.write,导致原来的HTML全部被覆盖。
    3.用警告框输出:alert(想要输出的内容); - 缺点:会卡主页面,只能看到警告框。
3.变量和常量
一.变量:简单来说就是一个值可以发生变化的数据/量。**
    什么时候使用:如果以后某一个数据我们要反复使用,最好都把他先保存成一个变量,
    以后只需要使用变量名相当于就是在使用变量的值;
    语法:var 变量名=(这里的=号是赋值的意思,把右边的东西保存到左边)值;
    特殊点:
    1、面试题:内存和变量有区别吗?
		硬盘:保存数据/文件,机械硬盘和固态硬盘 - 外存
		CPU:中央处理器 - 用于计算的
		内存:是程序在运行过程中【临时】用到的数据
		内存空间:实际保存数据的地方
		内存地址:内存空间的一个门牌号:
                    所以他们没有区别
    2、变量名其实不是随便的
		1、不能以数字开头
		2、建议:尽量的要见名知意:
			以英文为主:比如var name="xx";

	(拼音变量名)var xingming="某某某"; - (打字速度)很低,并且很low

			最不推荐:var aa; - 没有见名知意的效果
				  var ab;
				  var ac;
                                      3、使用驼峰命名法更加推荐
		4、有些字母是一个关键字,不管你保存的数
                    据类型是什么,都会悄悄的变成一个字符串
                    比如(name...)
		5、千万不要把关键字当做变量名
     3、如果你想要创建多个变量,没有必要每个都写var,
     中间的变量都可以省略掉var关键字,中间用,间隔,最后一个还是用;结束

比如: 变量简单写.png

4、算术运算符:+ - * / %:前四个运算符和小时候学习的一模一样
%:取余,俗称模,两个数相除,不取商,而取除不尽的余数
num1%num2;
   作用:
		1、*判断某个数字的奇偶性:num%2	如果结果为0说明是偶数,如果结果为1说明是基数
		2、取出一个数字想要的后n位
			1234%10	-> 4
			1234%100 -> 34
			1234%1000 -> 234
     特殊:
		1、算数运算符具有隐式转换(悄悄地,我们程序员看不见的),默认:都是转为数字在运算
		   特殊在+运算,如果碰到了一个字符串,两边都会悄悄的转为字符串,变成了一个拼接操作
		2、-*/%:其实字符串也能转为数字,但是前提是一个纯数字组成的字符串,但凡包含一个非
		   数字字符,则为NaN:纯粹的垃圾:Not a Number:直译,不是一个数字,但是确实是数字类型,
                       但是不在三界之中
				全是缺点:
					1、NaN参与任何算数运算结果仍为NaN
					2、NaN参与任何比较运算结果都为false 
5、数据类型:
原始/基本/值类型:51String - 字符串,取值有无数个,但是必须写上""''
		2Number - 数字,取值有无数个,直接书写数字即可
		3Boolean - 布尔,取值只有2true(真,对)和false(假,错) - 多半用于表示判断的结果
		4Undefined - 变量如果声明了,但是没有赋值的话,默认值就为undefined,只有这一个取值 
                    - 垃圾:没有任何用处
		5Null - 空,取值也只有一个null,释放内存/变量

引用/对象类型:11个对象(属性和方法)js主要就是学习这11个对象的使用方法

说了这么多,做点小练习吧

1.让用户来输入半径,计算此圆的面积和周长;

prompt这个单词可以让用户输入

我懒的写,我就把以前写过的截图拿来了,我用红色方框框起来的不用管,我只是进行了封装,封装以后好直接进行调用。

image.png

image.png

image.png

2、根据分数送礼物

image.png

image.png

image.png

3、计算标准体重:BMI 公式:weight/(height*height) - 体重单位kg 身高单位m

最后一个懒的截了

四、***数据类型的转换:【一切的页面上获取来的数据类型都是字符串】

JavaScript是一个弱类型的语言 有数据 决定了 我们的数据类型是什么 1 number "1" string

number + number = number
string + number = string

查看数据库类型:typeof(想要检查的变量);

1、*隐式转换:悄悄地我们程序员看不见的转换
   算术运算符具有隐式转换:
   作用:我们如果精通了隐式转换,我根本不需要console.log我也知道最后的结果是什么
	默认:都是转为数字,在运算
	特殊:  1、不管是什么运算,只要没碰上字符串,都会悄悄的转为一个数字
			true->1
			false->0
			undefined->NaN
			null->0

		2、+运算并且碰上字符串,则为拼接,最后的结果也就还是一个字符串

		3、-*/%,就算是字符串也可以转为数字,前提是纯数字组成的字符串
                    ,但是如果包含了一个非数字字符,则为NaN
			"1000" -> 1000
			"100a0" -> NaN

		NaNNot a Number:不是一个数字,但是确实是数字类型,只不过不在三界之内
			全是缺点:
				1、不在三界之内,不大于,不小于,不等于,任何值,包括自己
				2、参与任何算数运算+-*/%,结果仍为NaN

			问题:正是因为NaN参与任何比较运算结果都为false,甚至自己都不认识自己,
			      所以我们没有办法用一个普通的比较运算来判断x是不是NaN
			解决:!isNaN(x):此方法不管你放的x是什么都会悄悄的隐式转换为数字
				true->说明是一个有效数字
				false->说明是一个NaN
			      目的:防止用户恶意输入,但是目前为止,只能防止用户输入的必须是一个数字
                                  (比如验证的话我们做不了:正则学了才能做)
	

2、显式转换:也叫作强制转换:
   何时使用:隐式转换出来的结果不是我们想要的,先强制转换为需要的数据,再运算
   如何使用:
	1、转为字符串:
		var str=xx.toString();//xx不能是undefined和null,undefined和null不能使用.操作
		因为一切的页面上获取来的数据类型都是字符串

	2、*转为数字:3种
		*1parseInt(x); - parse解析 Int整型:解析为一个整数
		   执行原理:从左向右,依次读取每个字符,碰到非数字字符就停止,
                       不认识小数点,如果一来就不认识则为NaN
		   去掉单位

		*2parseFloat(x); - parse解析 Float浮点数:解析为一个小数
		   执行原理:几乎和parseInt一致,但是认识第一小数点
		   去掉单位

		以上两个方法很重要:但是x只能是数字或者字符串,不能是别的,如果是别的统一的认为是不认识的,
                    不认识的结果就为NaN了
		个人感觉,这两个方法是专门用于str to num

		3Number(x); - 万能的,任何人都可以转为数字,垃圾:此方法完全等效于隐式转换
				其实隐式转换的底层,就是悄悄地使用了此方法,所以我们绝对不会手动使用
				还不如 x-0 /1 *1 %1

五、*****Function:自定义函数:也称之为方法:需要【预定义好】的,可以【反复使用】的一个【代码段】

rotate(45deg) - 完成了一个根据角度值顺时针旋转45度的功能
url(图片路径) - 完成了一个根据图片路径显示图像的功能
...

js中的函数 - 完成了一个。。。。。。的功能

1、创建函数:

	function 函数名(){
		代码段;//若干操作
	}

2、调用函数:

	1、直接在js中程序员写几次调用,就会执行几次操作:
		函数名();

	2、让用户来自己触发:
		<elem onclick="函数名()"></elem>

3、以后何时使用函数:

	1、以后任何作业都要封装成一个函数,因为函数的js地位很高,属于第一等公民地位
	2、你不希望打开页面立刻执行
	3、能够反复执行
	4、他是个独立的功能体
	5、你不是自己释放内存,函数调用完毕会自动释放内存/变量

4、带参数的函数:

	电饭煲 -> 看做是一个函数:功能:把....煮熟
	原材料 -> 参数	
	
	语法:形参:其实就是一个变量名,只不过不需要写var这个关键字,每个形参之间用,
            间隔,形式参数,简称形参
		function 函数名(形参,...){
			函数体;
		}

	调用:实参:实际参数
		函数名(实参,...);

		function zwjs(name,age,hobby){
			console.log("我的名字叫"+name+",今年"+age+"岁,喜欢"+hobby);
		}
		zwjs("张三丰",128,"打太极");
		zwjs("张无忌",18,"撩妹");
		zwjs("张三",28,"说法");	

	特殊:实参的个数以及顺序 和 形参的个数以及顺序都要一一对应

5、普通函数:操作永远是固定的

   带参数的函数:根据传入的实参,执行略微不同的操作

六、***分支结构:

1、代码流程控制语句:
	1、顺序结构:默认的,代码从上向下

	2、分支结构:根据条件不同,选择部分代码执行

	3、循环结构:根据条件满不满足,考虑要不要再执行一次相同 或 相似代码

2、关系/比较运算符:> < >= <= == !=
	结果:一定都是一个布尔值

	注意:==才叫比较		=叫赋值:右边的东西放到了左边保存起来

3、逻辑运算符:
	&&:与(并且):全部条件都满足,结果为true
			只要有一个条件不满足,结果为false

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

	 !:颠倒布尔值

4、分支的语法:
	1、一个条件一件事,满足就做,不满足就不做
		if(条件){
			操作
		}

	2、一个条件两件事,满足就做第一件,不满足就做第二件
		if(条件){
			操作;
		}else{
			默认操作;
		}

	3、多个条件多件事:满足谁就做谁
		if(条件1){
			操作1;
		}else if(条件2){
			操作2;
		}else if(条件3){
			操作3;
		}else{
			默认操作;
		}

	else可以省略,但是不推荐

七、***循环结构

问题:在控制台打印输出10000句hello world

console.log("1hello world");
...
console.log("1000hello world");

解决:循环结构:反复执行相同 或 相似的代码

 生活中的循环:
	吃饭
	睡觉
	做作业
	上课
	上班
	活着

循环三要素:

	1、循环条件:从哪里开始,到哪里结束
	2、循环体:操作-要做什么事
	3、循环变量、变量还要变化

1、while循环:其实循环从宏观上看是一起执行的,但是微观上看是一次一次执行的,只不过这个执行速度很快 语法: var 循环变量=几; while(循环条件){ 循环体; 循环变量变化; }

执行原理:先判断循环条件满足吗,如果为true,
    则执行循环体一次,再一次判断循环条件满足吗,如果为true,则再执行循环体一次
	  .......直到循环条件不满足,才会退出循环

特殊:
  死循环:永远不会结束的循环,但是还真用:往往不确定循环次数的时候就要使用
	while(true){
		循环体;
	}

  往往死循环还要搭配上,退出循环语句:break; - 只能写在循环里面

2、***for循环:执行原理跟while一模一样,只是语法更加的简洁
for(循环变量的创建;循环条件;变量的变化){
	循环体;
}

特殊:1、循环变量的创建和循环变量的变化,其实可以写多个

      2、死循环:for(;;){操作}


总结:1while:语法更加繁琐,建议只用于不确定循环次数的时候 - 死循环
      2for:语法更加简洁,建议只用于确定循环次数的时候 - 大部分情况
	 
问题:函数 和 循环 都是可以反复执行的,区别在哪里?
	函数 - 要么程序员调用几次,执行几次,或者,用户来触发几次,执行几次
	循环 - 程序员写好的,而且几乎是一瞬间就执行完毕了的

八、*****数组:

问题:保存1000个同学的姓名: var name1="周洁"; var name2="周杰"; var name3="周杰伦"; ... 以上写不合理:变量就是一个内存,我们开辟的内存空间太多的话,会影响网页效率 希望,一个变量名,就可以保存住所有的数据 - 数组:

   数组里面的元素,是按照线性顺序排列的,除了第一个元素,每个元素都有一个唯一的前驱元素
				除了最后一个元素,每个元素都有一个唯一的后继元素
*每个元素都有一个唯一的位置序号,称之为【下标】:从0开始,到最大长度-1

1、创建数组:2种 1、*直接量方式:var arr=[];//空数组 var arr=[元素,...];

2、构造函数方式:var arr=new Array();//空数组 - 个人不推荐,更麻烦,其实直接量方式是ES2过后才添加上的,
    原来只有构造函数方式
		var arr=new Array(元素,...);

2、访问/获取:获取出数组中的某个元素

数组名[下标]

3、添加/覆盖:

数组名[下标]=新元素;
特殊:
  1、下标处没有元素,则为添加
  2、下标处有元素,则为覆盖/替换

4、数组的三大不限制:

1、不限制元素的类型
2、不限制元素的个数
3、不限制下标越界 - 算是一个缺点:
	获取时 - 下标越界,返回undefined
	添加时 - 下标越界,会变成稀疏数组,导致下标不连续,不好

5、数组有一个唯一的属性:数组名.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];//当前次元素
	}

九、JavaScript其实由三部分组成:

1、ECMAScript(3/5/6)- 核心语法:我们天天在做应用题,语法很关键 - 内功心法
2、DOM - Document Object Model:文档对象模型,外功招式 - 操作文档(html/css)
3、BOM - Browser Object Model:浏览器对象模型,外功招式 - 操作浏览器(相对较少)- 兼容性问题

#2、DOM概述:Document Object Model:文档对象模型,外功招式 - 操作文档(html/css) DOM树:DOM将HTML看做了是一个倒挂的树状结构:树根其实是一个叫做:document的对象 document对象:不需要我们创建,一个页面自带一个document对象,由浏览器的js解释器自动创建 *作用:只要是对象一定有两个东西(属性和方法):提供了我们找到元素&操作元素的方法

3、查找元素:

1、通过 HTML 特性去查找元素 1、通过ID查找元素:

	var elem=document.getElementById("id值");//get得到 element元素 by通过
	特殊:
	  1、如果有多个相同的id,只会找到返回第一个 - id是唯一不重复的
	  2、*返回的结果:<li id="li">油条</li> - 这个才能称之为叫做一个DOM元素/节点/对象,
              才可以用于下午的操作
	  3、你不准用这个方法 - 我们把id留给后端使用,而且id也不好用,一次只能找到一个元素

2、通过标签名查找元素:

	var elems=document/parent.getElementsByTagName("标签名");
	特殊:
	  1、返回的结果:不是一个DOM元素/节点/对象,是一个DOM集合,是不能直接用于做任何操作的
		解决:要么用下标拿到某一个,要么用遍历拿到每一个
	  2、parent:代表的是你已经找到的某个父元素

3、通过class名查找元素:

	var elems=document/parent.getElementsByClassName("class名");
	特殊:
	  1、返回的结果:不是一个DOM元素/节点/对象,是一个DOM集合,是不能直接用于做任何操作的
		解决:要么用下标拿到某一个,要么用遍历拿到每一个
	  2、parent:代表的是你已经找到的某个父元素

2、通过 关系 获取元素:前提:至少要先找到一个元素:

父元素:elem.parentNode; - 单个元素
子元素:elem.children; - 集合:集合不能直接做操作
第一个儿子:elem.firstElementChild; 
最后一个儿子:elem.lastElementChild;
前一个兄弟:elem.previousElementSibling;
后一个兄弟:elem.nextElementSibling;

4、操作元素:

image.png

1、内容:

1、innerHTML:获取 或 设置元素的内容部分,并且能够识别标签

	获取:elem.innerHTML;
	设置:elem.innerHTML="新内容";

2、innerText:获取 或 设置元素的文本部分,不能识别标签

	获取:elem.innerText;
	设置:elem.innerText="新文本";

以上两个操作都是针对双标签使用

3、value:获取 或 设置input的内容部分

	获取:input.value;
	设置:input.value="新文本";

2、属性:

1、获取属性值:

       elem.getAttribute("属性名");
       简化版:elem.属性名;

2、设置属性值:

       elem.setAttribute("属性名","属性值");
       简化版:elem.属性名="新属性值";

简化版虽然简单,但有缺陷: 1、class必须写为className 2、只能操作标准属性,不能操作自定义属性

个人建议:优先使用简化版,简化版满足不了,再用复杂版做补充

3、样式:

样式有三种使用方式:
	1、内联
	2、内部
	3、外部 - 符合内容HTML与样式CSS与行为JS的分离原理

如何使用:

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

	特殊:1、设置css属性名如果有横线要去掉横线,变为小驼峰命名法
	      2、获取只能获取到内联样式 - 忍忍就过了

获取:往往用于判断
设置:其实就是修改

5、绑定事件: 符合内容HTML与样式CSS与行为JS的分离原理

单个元素:
	elem.onclick=function(){
		this->就是绑定事件的这个元素
	}

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