1、JavaScript概述:
1、**什么是JavaScript**:
简称为JS,是运行在【JS解释器】的【解释型】【弱类型】【面向对象】脚本语言
** 2、JS解释器:**
1、浏览器自带js解释器,不需要安装可以直接使用
2、以后我们学习Node.js还会安装一个独立的js解释器
** 3、编译型**:运行之前需要检查语法是否正确,如果不正确直接不能运行,比如:Java、c、c++、c#... - 比较严格
解释型:运行之前不需要检查语法是否正确,直接运行,如果碰到错误就会停止后续代码,比如:JavaScript、php - 比较自由
**4、弱类型**:由 数据 决定了 数据类型是什么 - 比如javascript - 更自由
1 - number数字
"1" - string字符串
强类型:由数据类型 决定了 你这个变量能保存什么数据 - 比如:Java - 更严格
**5、面向对象**:以后你会经常见到这种语法
对象名.属性名;
对象名.方法名();
万物皆对象,比如:人(属性:身高、体重、姓名、性别、年龄)、杯子、电脑、轮播、购物车
(方法:吃饭、睡觉、拉屎、喝水、玩游戏)
**6、js的特点**:
1、代码可用任何编辑器编写(HBuilder、VScode、atom、webstorm、记事本....)
2、解释型、弱类型、面向对象
3、用途:1、实现所有css完成不了的效果
2、和服务器端进行交互沟通 - ajax(j:JavaScript)
2、JS的使用 - 代码:
1、如何在html上书写js:2种
1、在HTML页面上写一个script标签,在里面编写你的js代码 - 上课用,更轻松
<script>
//js代码
</script>
2、正式开发中 - 在外部创建一个js文件,里面编写你的js代码,记得要引入
<script src="路径"></script>
2、***输出的方式:3种 - 作用:测试语句,打桩输出,找错的方式
*1、console.log(想要输出的内容) - 在F12的控制台console查看 - console控制台 log日志
2、document.write(想要输出的内容) - 在页面body上输出 - document当前文档 write写入,缺点:只要搭配上点击事件,则会替换掉当前页面原有的所有内容
3、alert(想要输出的内容) - 在一个弹出警告框上输出,缺点:会卡住整个页面(只能看到一个白板)
3、注释:
单行注释://
多行注释:/**注释**/
作用:
1、可以方便我们记忆或者提示程序员,方便维护
2、玩 - 神注释
4、***变量:变量的特点数据是可以改变的
硬盘:存储文件、数据 - 外部存储器
CPU:中央处理器 - 用于计算
内存:是【临时保存】程序运行中,所需要用到的数据,变量其实就可以说是一个内存空间
内存空间:保存数据的一个地方
内存地址:内存空间的一个门牌号,0x00000321a21468b71987,如果内存地址过长,不方便记忆,我们可以去一个别名(变量名)来代替
语法:var 变量名=值;
何时使用:以后只要反复使用的数据,都要提前保存成一个变量,方便以后使用
特殊:
1、变量名不是随意的:
1、不能以数字开头
2、不能使用关键字
3、尽量要见名知意
千万不要:会导致这段代码,以后没人看得懂,没有知道这个变量到底用来干什么了
var aaa;
var aab;
var aac;
尽量不要:会导致这段代码,逼格太低了
var xingming;
var nianling;
var xingbie;
尽量要:用英文,不会就翻译,顺便多学点单词
2、其实var 变量名;这句话就代表此变量已经创建好了,但是未赋值,默认值为undefined,
undefined我们不希望见到他,他拿来干什么都要不得,建议:创建变量的时候尽量的要记得及时赋值=
3、赋值符号:=,把等号右边的数据保存到等号左边,左边一定是一个变量名
4、name其实是一个关键字,不管你保持什么数据类型,最后都会隐式(悄悄的)变成一个字符串
5、以后不管呆老湿说是声明/创建/定义变量,都是一个意思
5、常量:一旦创建了就不允许修改了 - 生活中少的,代码中也少
生活中的常量:
1、籍贯
2、一天24个小时
3、一个小时60分钟
4、PI - 3.1415926....
语法:const 常量名=值;
6、运算符:
1、算术运算符:+ - * / %
前四个+ - * /,和小时候学的一模一样,没有变化
%:读取取余或者模,m%n,翻译:m除以n,不取商,而取除不尽的余数
%作用:
1、*判断奇偶性
num%2==0 偶数
num%2==1 奇数
2、获取一个数字的后n位:
1234%10 -> 4
1234%100 -> 34
1234%1000 -> 234
3、控制一个结果永远不超过几
num%5 -> 结果永远不会超过5
***算术运算具有隐式转换,默认为转为数字,再运算
特殊:+运算,如果碰到了一个字符串,那么两边都会悄悄的转为一个字符串,然后+运算也不再是+运算,变为拼接操作
7、数据类型:2大类:
1、原始/基本/值类型:5个
1、String - 字符串,取值有无数个,必须 "" 或 '' 包裹
2、Number - 数字,取值有无数个,不需要任何包裹
3、Boolean - 布尔,取值只有2个,true和false,代表真(对)和假(错) - 判断/比较的时候出现
4、Undefined - 取值只有一个:undefined,变量未赋值时的默认值,而且没有任何用处
5、Null - 取值只有一个:null,空,释放内存/变量,你用完了的变量都要记得释放一下,节约内存空间
2、引用/对象类型:11个对象(属性和方法),等着以后我们慢慢学习,这也是为什么JavaScript要学4周多
扩展:
1、用户输入框:var user=prompt("提示文字","默认值");
2、分支结构:作用:根据条件,选择部分代码执行
语法:
1、一个条件一件事,满足就做,不满足就不做
if(条件){
操作
}
2、一个条件两件事,满足就做第一件,不满足就做第二件
if(条件){
操作
}else{
默认操作
}
3、多个条件多件事,满足谁就做谁
if(条件1){
操作1
}else if(条件2){
操作2
}else{
默认操作
}
注意:
1、最后的else可以省略,但是不推荐,如果条件都不满足,则什么都不会执行
2、else if想写多少个,需要根据你的需求来考虑
3、只会走一条路,走了一条路,不会去别的路
4、考虑好执行的顺序
*只要页面上的一切数据(文字、样式、用户输入的东西),数据类型都是一个字符串
1、***数据类型转换:
JavaScript是弱类型语言,由数据 决定了 数据类型是什么
对于不同数据类型的运算时,数据类型回进行自动转换:
number + number = number
number + string = string
如果你希望看到数据类型到底是什么:
console.log(typeof(变量))
1、*隐式转换:我们程序员看不见,悄悄的进行数据类型的变化
目的:提升我们程序员效率,我不用输出,我心算心里也知道最终结果是什么
算术运算符的隐式转换:
默认两边都会悄悄的转为是数字再运算
特殊:1、+运算,碰到一个字符串,两边都会悄悄的的转为字符串,再拼接起来
2、其他类型转为数字会为:
true->1
false->0
undefined->NaN
null->0
3、其实-*/%,字符串也可以转为数字,但是前提必须是纯数字组成的字符串才可以,但凡包含了一个非数字字符则为NaN
"100"->100
"100px"->NaN
4、NaN:Not a Number直译为不是一个数字,但是我们确实发现他是数字类型(蓝色的)
全是缺点:
1、参与任何算术运算结果都为NaN
2、参与任何比较运算结果都为false - 不在三界之内,不是一个有效数字
问题:通过第二个缺点,我们知道了,不能使用普通的比较运算来判断x是不是NaN,因为NaN自己都不认识自己,那么怎么判断是不是NaN呢
解决:
!isNaN(x); -> 判断x是不是一个有效数字,而且此方法会将x隐式转为数字
true->有效数字
false-> NaN
就是在控制用户必须输入的是一个数字,但是目前也只能控制用户输入数字,想要更严格控制需要以后学习正则才可以
目前就算学完了隐式转换,我们依然没有解决一个问题
"100px"+100 -> "100px100"
"100px"*2 -> NaN
2、*强制/显示转换:隐式转换出来的结果不是我们想要的,程序员可以手动调用某些方法实现的数据类型转换
1、转为字符串:
var str=x.toString();//null和undefined不能使用,null和undefined不能使用.去做任何操作
绝对不会用:页面上的数据默认都是字符串
2、***转数字:
1、*var num=parseInt(str/num); parse解析 Int整型:解析为一个正数
执行原理:专门为【字符串转为数字】准备,从左向右,依次读取每个字符,碰到非数字字符则停止,如果一来就碰到不认识的字符,则为NaN,不认识小数点
console.log(parseInt(35.5));//35
console.log(parseInt("35.5"));//35
console.log(parseInt("3hello5"));//3
console.log(parseInt("35px"));//35
console.log(parseInt("px35"));//NaN
console.log(parseInt(true));//NaN
console.log(parseInt(false));//NaN
console.log(parseInt(undefined));//NaN
console.log(parseInt(null));//NaN
2、*var num=parseFloat(str); parse解析 Float浮点型:解析为一个小数
执行原理:几乎和parseInt一致,认识第一个小数点
console.log(parseFloat(35.5));//35.5
console.log(parseFloat("35.5"));//35.5
console.log(parseFloat("3hello5"));//3
console.log(parseFloat("35.5px"));//35.5
console.log(parseFloat("px35"));//NaN
console.log(parseFloat(true));//NaN
console.log(parseFloat(false));//NaN
console.log(parseFloat(undefined));//NaN
console.log(parseFloat(null));//NaN
console.log(parseFloat("35.5.5"));//35.5
3、Number(x);//万能的,任何人都可以转为数字,包括undefined和null都能转,垃圾
//完全等效于隐式转换,还不如x -0 *1 /1
parseXXX vs Number:
1、Number:绝对不要手动使用,还不如 -0 *1 /1来触发隐式转换
2、parseXXX:只要你希望字符串转为数字,必用,转整数还是小数需要自行判断
2、*****Function的基础:
url(图像路径):完成了一个根据图像路径显示图像的功能
rotate(360deg):完成了一个根据角度值顺时针旋转360度的功能
js的自定义函数:完成了一个.........的功能
1、什么是函数:也称之为方法,是一段被【预定义好】的,可以【反复使用】的【代码段】
2、创建函数 以及 功能:
语法:
function 函数名(){
函数体;//若干操作
}
注意:函数定义好之后,不会立刻执行,只有再【调用】之后才会执行
3、调用函数:
1、直接在js里书写:函数名(); - 需要程序员来操作,程序员调用几次就执行几次
2、交给用户,把函数绑定在页面元素上,用户来触发事件,触发几次就执行几次
<elem onclick="函数名()"></elem>
4、什么东西适合封装在函数之中:
1、不希望打开页面立刻执行,可能是让用户来触发
2、有可能被反复执行的代码,重复的代码
3、本身就是一段独立的功能体:你的每一个作业都是一个独立的功能体(以后你的每一个作业都可以封装为一个函数)
4、函数的地位在js里非常高,属于第一等公民地位,尽量的考虑能不能封装为函数,函数中的【变量会自动释放】
5、带参数的函数:
榨汁机 -> 函数:功能:榨汁
原材料 -> 参数:放入一个苹果、梨子...
如何定义带参数的函数:
1、创建:
//形参列表其实就是变量,只不过这里的变量不需要关键字var,可以放多个,中间用,间隔,并没有保存住真正的值,所以是一个形式参数,简称为形参
function 函数名(形参列表){
函数体;//若干操作
}
2、调用:
//调用带参数的函数,必须向里面传入实际参数,简称为实参
函数名(实参列表)
注意:
1、传入实参的顺序要和形参对应上
2、传入实参的个数要和形参对应上
3、函数不一定非要有参数:具体情况具体分析
1、如果你是固定的函数体操作,不需要传入参数 - 普通函数
2、如果你希望根据传入的实参的不同,结果略微不同,则带参数的函数才能满足你
3、***分支结构 :
1、程序一共有三种结构:
1、顺序结构:默认结构,从上向下,依次执行每一行代码
2、分支结构:根据判断条件,选择一部分代码去执行(只会选择一条路走)
3、循环结构:根据判断条件,选择是否需要重复执行某一段代码
2、回顾语法:
1、一个条件一件事,满足就做,不满足就不做
if(条件){
操作
}
2、一个条件两件事,满足就第一件,不满足就做第二件
if(条件){
操作
}else{
默认操作
}
3、多个条件,多件事,满足谁就做谁
if(条件1){
操作1
}else if(条件2){
操作2
}else{
默认操作
}
注意:1、else可以省略,但是不推荐
2、else if想写多少个,看你自己,看需求
2、关系/比较运算符:> < >= <= == !=
以上6个运算符的结果一定都是一个布尔值:true、false
往往比较运算就会出现在分支、循环的条件之中
3、逻辑运算符:用于综合判断的
&&:并且、与
全部条件都为true,结果才为true
只要有一个为false,结果则为false
||:或者
全部条件都为false,结果才为false
只要有一个为true,结果则为true
!:非 - 颠倒布尔值
!true -> false
!false -> true
1、***循环结构
1、问题:在控制台打印输出1000句今天是星期三?
console.log("1今天是星期三");
...
console.log("1000今天是星期三");
2、什么是循环:【反复执行相同 或 相似的操作】
生活中:
1、吃饭
2、睡觉
3、学习
4、上班
5、活着
循环特点:循环三要素
1、循环条件:开始、结束:重复执行多少次
2、循环体:循环的操作:要做什么
3、循环变量 以及 变量要变化
3、while循环:
语法:
var 循环变量=几;
while(循环条件){
循环体;
循环变量变化起来;
}
执行原理:先判断循环条件,如果条件为true,则会执行【一次】循环体
然后再一次判断循环条件,如果条件为true,则会再执行【一次】循环体
...
直到循环条件为false,才会退出循环执行后续代码
注意:从宏观上来看,循环好像是一瞬间就完成的
但是从微观上来看,循环其实是一次一次执行的,不是同时执行的,只不过我们电脑的速度比较快
死循环:永远不会结束的循环 - 【不确定循环次数的时候】就使用死循环
while(true){
循环体;
}
*但是死循环多半都要搭配上停止循环语句:break一起使用,要不然电脑都可有可能会死机
4、***for循环:
语法:
for(var 循环变量=几;循环条件;循环变量的变化){
循环体;
}
特殊:1、死循环:for(;;){操作}
2、循环变量处可以用,隔开创建多个
while vs for:
1、while - 语法脏乱差,而且一般只适用于不确定循环次数的时候使用 - 死循环,非常少见,确实会见到
2、for - 语法非常舒服,而且一般只适用于确定循环次数的时候使用 - 大部情况都会使用for循环
小结:函数和循环都可以反复执行,他们的区别在哪里呢?
1、时机:
函数 - 多半都是用户来触发
循环 - 感觉上几乎是一瞬间就结束了
2、*****数组的基础:
1、问题:保存1000个人的姓名:
var name1="袍哥1";
...
var name1000="袍哥1000";
创建了1000个变量,意味着开辟了1000个内存空间,性能消耗较大,网页性能低下
解决:数组:多个元素/数据组成的一个集合,保存在一个变量名:一个变量可以保存多个数据
数组中的元素都是按照线性顺序排列:
除了第一个元素,每个元素都有唯一的前驱元素
除了最后一个元素,每个元素都有唯一的后继元素
***数组中每个元素都有一个唯一的位置序号,称之为【下标】,下标都是从0开始的,到最大长度-1
2、创建数组:2种方式
*1、直接量方式:var arr=[];//空数组
var arr=[数据,数据,....];
2、构造函数方式:var arr=new Array();//空数组
var arr=new Array(数据,数据,....);
3、访问数组中的元素:
数组名[下标];
4、追加/替换元素:
数组名[下标]=值;
当前下标有没有元素,如果有,则为替换,如果没有,则为追加
5、数组具有三大不限制:
1、不限制元素的类型
2、不限制元素的个数
3、不限制下标越界 - 不是优点了:
获取时,下标越界,得到undefined(拿来干什么都是垃圾)
追加时,下标越界,会导致数组变为稀疏数组,下标不再连续,如果有一天我们去遍历数组,我们必然会得到很多很多的undefined
6、数组唯一的属性:length - 长度
语法:数组名.length - 获取到此数组的长度
***三个固定套路:
1、向末尾添加元素:arr[arr.length]=值;
2、获取倒数第n个元素:arr[arr.length-n];
3、缩容:删除倒数n个元素:arr.length-=n;
7、遍历数组:把数组中的【每个元素取出来】【执行 相同 或 相似的操作】 - 循环数组得到每个元素
公式:
for(var i=0;i<arr.length;i++){
console.log(arr[i]);//当前次元素
}
1、JavaScript由三部分组成:
1、ECMAScript(ES3/5/【6】/7/8/9/10/11/12/13)- 核心语法:前三天都在学习的内容 - 内功心法
2、DOM - Document Object Model:文档对象模型 - 外功招式,专门用于操作当前文档的(操作HTML)3、BOM - Browser Object Model:浏览器对象模型 - 外功招式,专门用于操作浏览器的(相对于DOM使用较少,但也有重点)
2、DOM概念:
DOM树:把HTML看作了是一个倒挂的树状结构,但是树根不是大家理解的html标签,而是document这个对象(属性和方法)
document对象是不需要我们创建的,浏览器的js解释器会自动创建,一个页面只有一个document对象
提供了很多属性和方法,等待我们去学习
注意:DOM会把页面上的所有元素、属性、文本、注释都视为是一个dom节点/dom元素/dom对象
3、获取元素:2个大方向
1、通过 HTML 的特点去获取元素
1、通过 ID:var elem=document.getElementById("id值")
特殊:
1、id如果重复了,只会找到第一个,id的唯一性
2、如果没找到,返回的是一个null
3、*你输出看清楚,长成这个样子<li id="li1">尖椒拱嘴</li> - 我们才能称呼是一个dom节点/dom元素/dom对象,才可以拿去下午做操作
4、此方法不准用,白学 - 缺点:1、一次只能找一个元素,意味着只能操作一个元素 2、id留给后端用
2、*通过 标签名:var elems=document/parent.getElementsByTagName("标签名")
特殊:
1、返回的是一个类数组对象/集合,长得像数组,并不是数组,只不过也可以使用下标,也可以使用length,也可以遍历,有很多东西和数组是不一样的
2、*一个集合不能直接做操作,要么下标拿到某一个,要么遍历拿到每一个
3、如果没找到,返回的是一个空数组
4、此方法不一定非要写document,也可以是parent:是你已经找到的某个父元素
3、*通过 class名:var elems=document/parent.getElementsByClassName("class名")
用法完全等效于标签名用法
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、属性:
获取属性值:elem.getAttribute("属性名");
设置属性值:elem.setAttribute("属性名","属性值");
简化版操作:
获取属性值:elem.属性名;
设置属性值:elem.属性名="属性值";
2个小缺陷:
1、class必须写为className
2、只能操作标准属性,不能操作自定义属性
建议:开发中优先使用简化版,简化版实现不了的再用复杂版补充
3、样式:
一阶段学习了操作样式的3种方式:
1、内联样式 - 二阶段js操作就要他
优点:1、优先级最高 - 绝对能生效
2、不会牵一发动全身 - 只会修改当前元素
缺点:1、获取时,也只能获取到内联样式 - 可以忽略不计
2、内部样式表
3、外部样式表 - 喵喵说一阶段写样式就用它
获取样式:elem.style.css属性名;
设置样式:elem.style.css属性名="css属性值";
特殊:css属性名由横线的地方,去掉横线,换为小驼峰命名法
4、绑定事件:不要像以前一样,写在HTML上,不符合我们内容(HTML)与样式(CSS)与行为(JS)的分离
elem.onclick=function(){
操作;
//事件中有一个关键字:this(指针),今天的最后一个重点
单个元素绑定事件:this指向就是这个元素
多个元素绑定事件:this指向就是当前触发事件的元素
}
强调:操作
一切的获取,都是为了判断|比较
一切的设置,都是为了修改