初识JavaScript
一 . 概念
JavaScript是一门运行在浏览器端的解释型,弱类型的面对对象脚本语言;
-
运行环境:(浏览器端)打开浏览器就可以运行,浏览器内部有自带的js解释器
-
编译类型:
1. (解释型--自由)编译前不检查语法错误,有没有错误,都直接运行,运行到错误那一行停止运行并报错;
2. (编译型--严格)编译前先检查语法错误,若有错误,直接不运行; -
语言类型:
1. (弱类型--自由)声明变量的数据类型由数据本身决定,用关键字 var x = 1;
2. (强类型--严格)声明变量的数据类型由关键字决定,如:int i=0;/ strig str="abc"; -
面向对象:*
对象的含义是指具体的某一个事物,即在现实生活中能够看得见摸得着的事物。在面向对象程序设计中,对象所指的是计算机系统中的某一个成分。在面向对象程序设计中,对象包含两个含义,其中一个是数据,另外一个是动作。对象则是数据和动作的结合体。对象不仅能够进行操作,同时还能够及时记录下操作结果。
二 . js组成部分
- ECMAscript:核心语法ES3、5、6、7、8、9、10、11、12;
- DOM:Document Object Model,文档对象模型
- BOM:Browser Object Model,浏览器对象模型
三 . HTML页面中 js使用语法
- <script>//js代码段</script>
- <script src="js文件路径">//这里不写代码</script>
四 . js输出方式
-
控制台打印输出日志 ---- console.log("输出内容"); //推荐
-
页面文档输出日志 ---- document.write("输出内容");
//不推荐,因为输出之后会将原页面的所有内容都替换掉,不可取 -
警示框输出 ---- alert("输出内容");
//alert输出多个变量, 变量类型相同记得+"",变量类型不同,拼接写+全部转字符串,写逗号会只识别第一个变量,上面两种逗号和加号都行
//缺点:在浏览器中偶尔会把页面卡成白板,让页面内容消失。
五 . 变量 / 常量
-
变量:用于存放代码中需要反复使用/修改操作的数据,创建后可以修改
声明:var 变量名 = 值;
例如:var x = 1;
注意:
1 . 变量名命名要遵循:
(1)不能以数字开头
(2)语义化命名,见名知意
(3)规范命名(驼峰/脊柱)
2. -
常量: 用于存放代码中需要反复使用/无需修改的数据,创建后不可修改
声明:const 常量名 = 值;
例如:const pi=3.1415926;
六 . 数据类型
1 . 原始/基本/值 类型
(typeof(变量);//查看值类型)
| 数据类型 | 取值 | 控制台输出颜色 | 例子 | 转换为数字类型 | 作用 |
|---|---|---|---|---|---|
| 数字 ( number ) | 无数个 | 蓝色 | var x = 100; | 100 | |
| 字符串 ( string ) | 无数个 | 黑色 | var y="abc"; | NaN | |
| 布尔类型 ( boolean ) | true / false | 蓝色 | var bool = true; | 1 / 0 | 存放布尔值用于判断操作 |
| 空值 ( null ) | null | 灰色 | var x = null; | NaN | 唯一作用是释放内存 |
| 未定义 ( undefined ) | undefined | 灰色 | 未赋值变量的默认值 | 没有用 |
七 . 运算符
1 . 算术运算符( + - * / %)
% : 取余,俗称模,两数相除取余数,作用:(1)余数判断奇数偶数(2)取出数字的后n位
特殊 :
-
(1)算术运算符带有隐式转换:会默认将符号两边的数据类型都转为数字类型
true ---- 1 false ---- 0 null ---- 0 undefined ---- NaN "1000" ---- 1000 "100px" ---- 要用parseInt();强制转换 -
(2)+ 号两边若出现字符串,会将两个数据都隐式转换成字符串类型,操作变成字符串拼接
2 . 比较/关系运算符( > / < / = / <= / <= / != / === / !==)(结果一定是布尔值)
特殊 :
(1)如果参与比较的是字符串,就会依次按位pk字符串的ASCII码(十进制) 或者 Unicode码(十六进制);( 0-9 < A-Z < a-z < 汉字)
(2)NaN参与任何关系运算结果都是false,包括和他自己
NaN (Not a Number) 不是一个数字,却是number类型
!isNaN();判断是否是数字类型,返回布尔值
(3)undefined == null //true
3. 赋值运算符 += -= *= /= %=
i+=5; ----> i=i+5;
4. 自增自减运算符 ++ --
面试题:前++和后++区别; i++/++i
1. 如果不参与表达式运算,那么两者没什么不同
2. 如果参与表达式运算, i++返回的是旧值用于参加运算,就是i的值
++i返回的是新值用于参加运算,是i++后的值
比如i=5;i++ + ++i == 12
5 + 7
5. 逻辑运算符(&&与、||或 、!非)
(1)&& 全真才真,一假为假
(2)|| 一真为真,全假才假
(3)! 布尔值取反
6. 位运算(<<左移 >>右移)
(1)左移 m<<n(m左移n位)--- m * 2的n次方
(2)右移 m>>n(m右移n位)--- m / 2的n次方
七 . 程序的流程控制语句 ( 顺序结构,分支结构,循环结构 )
( 1 ) 顺序结构:默认 ---- 从上到下依次执行语句
( 2 ) 分支结构:(3种)通过条件判断,来决定执行哪一个代码段
1 .if...else 分支
-
( 1 ) if (条件) { 操作; }
//一个条件,一个操作,满足就做 -
( 2 ) if ( 条件 ) { 操作1; }
else { 默认操作; }
//一个条件,两个操作,满足做操作1,不满足就做默认操作 -
( 3 ) if ( 条件1 ) { 操作1; }
else if ( 条件2 ){ 操作2; }
......
else{ 默认操作; }
//多个条件,多个个操作,满足哪个条件做哪个操作,都不满足就做默认操作
2 . switch...case 分支
- ( 1 ) 语法:<br>
- switch(变量/表达式){
case1: 值1 //变量 == 值1 的时候执行操作1
操作1;
break;
case2: 值2
操作2;
break;
case3: 值3
操作3;
break;
.......
case n: 值n
操作n;
break;
default:
默认操作
}
//特殊 :
(1)如果不加break,默认只要满足一个case就会把后续操作全部做完,最后一步default执行完就退出了,可以不加break;
(2)case在做等值比较时不带隐式转换,注意数据类型!
(3)中间多个case值一样可以省略不写;
(4)default可以不写但是最好不要,如果条件不满足就会无事发生。
面试题:if 和 switch 分支的区别?
| 类型 | 优点 | 缺点 |
|---|---|---|
| if | 可以做范围判断 | 执行效率慢,因为是范围判断 |
| switch | 执行效率高,因为是等值比较 | 必须知道结果是什么才可以设置比较值 |
3 . 三目运算符 --- 简化分支
(1)单条件语法:条件 ? 操作 : 默认操作 ;
//相当于if...else
(2)多条件语法:条件1 ? 操作1 : 条件2 ? 操作2 :.....:默认操作;
//相当于if...else if...else;
特殊:建议条件少的用,条件多用前两种,默认操作不能省略,否则报错。
( 3 ) 循环结构:(3种)通过条件判断,来反复执行相同或者相似的操作
循环三要素 :
1. 循环条件 : 开始到结束循环的次数 (比如 var i=0;i<10;)
2. 循环体 : 需要循环的代码段
3. 循环变量 : 记录当前正在做第几次循环,做完就自增(i++)
循环执行原理 :
- 创建循环变量
- 判断循环条件,满足执行循环体,不满足则不执行
- 执行一次后仍然满足循环条件,则再次循环
- 直到不满足循环条件再退出
1 . for 循环
语法 : for ( var 循环变量=值;循环条件;循环条件变化; ) { 循环体; }
特殊 :
( 1 ) 定义循环变量时还是要var一下,否则全局污染
( 2 ) 死循环的运用 : for( ; ; ){ 循环体; (判断后break;) } , 用于不知道循环次数的循环,满足条件后要搭配break跳出循环,否则会卡死
2 . while 循环
语法 :
var 循环变量 = 值 ; //一般是0或1
while ( 循环条件 ) {
循环体;
循环变量变化; // i++;
}
特殊 :
(1) 死循环 : while( true/1 ), 必须搭配 break / continue 使用
- break : 退出循环 , 不再执行循环
- continue : 退出本次循环 , 若符合循环条件 , 下一次接着循环
面试题 : for 循环 和 while 循环 的区别?
答 : 原理上二者没有区别,但是一般来说
确定循环次数 ------ 大部分用for
不确定循环次数 ---- 用死循环 , 记得break
3 . do...while() 循环
语法 :
var 循环变量 = 值 ; //一般是0或1
do{
循环体;
循环变量变化; // i++;
}while ( 循环条件 )
面试题 : while 循环 和do...while 循环 的区别?
答 : 区别在第一次执行
while ---- 第一次执行,条件不满足就不会执行
do...while ---- 第一次执行,先执行一次再判断条件,所以即使条件不满足,也会执行一次
八 . 强制数据类型转换 / 显示数据类型转换
1. 转字符串类型 ( String();//万能 )
方法:
( 1 ) var str = x . toString ( ) ;
//toString 方法,只能面对对象使用,x不能等于undefined 和 null
( 2 ) str =String(x);
( 3 ) x + ""
//利用 + 符号的隐式转换 ,加上一个空字符串,两边都转化为字符串类型, x + ""
2. 转数字类型 ( Number();//万能 )
方法:
( 1 ) parseInt(str/num);
//parse(解析) 字符串或数字转为整数类型
//原理 : 是从左到右依次解析,遇到非数字字符就停止转换,第一个都不认识,就是NaN
//例如 : parseInt("1000px"); ---- > 1000
( 2 ) parseFloat(str/num);
//字符串或数字转为浮点数类型,原理同上,只认识第一个小数点,遇到第二个就停止转换
( 3 ) x-0 x*1 x/1
//利用运算符号的隐式转换 ,两边都转化为数字类型, 加号特殊不用
3. 转布尔类型 (Boolean();//万能)
特殊 : 只有6个值转换为布尔类型后取 false 值 , 其余都取 true
0 / "" / null / undefined / NaN / false
函数 ( Function )
一 . 概念 :
先预定义好一个函数/方法 , 之后可以反复调用的代码段 , 创建好不执行 , 调用才执行
二 . 函数如何使用 :
( 1 ) 定义 / 创建 / 声明 一个函数
1 . 直接声明 :
-
function 函数名(形参列表){ 操作; return 返回值/结果; //没有形参也可以返回值到全局,在全局用变量接住就可以继操作 }
1 . 直接量方式 :(不推荐)
-
var 函数名 = function(形参列表){ // 函数名相当于变量名 操作; return 返回值/结果; }
( 2 ) 函数的调用
1 . 函数中直接调用 : 函数名();
2 . HTML页面中调用 : 给元素绑定onclick事件 , 再调用
<elem onclick="函数名()"></elem>
3 . return 的使用 :
全局想用局部的私有的东西 , 就可以返回到全局 , 再用变量接住 ,就可以使用了.
var 变量 ( 用于接住返回结果 ) = 函数名 ( 实参列表 ); //将实参传进函数进行操作
注意 :
1 . return的本意是退出函数并返回一个值 , 本身没有保存值的功能 , 所以需要用一个变量接住才能使用;
2. 省略 return , 也会默认返回一个 undefined ;
三 . 函数的作用域 :
- 全局作用域 : 全局变量 / 全局函数 , 在页面的任何一个位置都可以使用 , 包括局部;
- 局部作用域 : 局部变量 / 局部函数 , 只能在局部内可以使用 , 但是局部使用未var就直接赋值的变量会造成全局污染 ;
!! 带来变量的使用规则 : 局部内优先使用局部的变量,局部没有就找全局要,全局也没有,就会报错undefined,如果在局部对变量直接赋值,就会造成全局污染
!! 全局污染 : 若在函数中对未声明的变量直接赋值,就会导致全局本身没有这个变量,但是被函数作用域给添加上了,会增加内存,后续要是全局使用了这个变量会造成污染
四 . 声明提前 : ******** 开发不使用,只出现在笔试
1. 规则 :
在程序正式执行之前,会把 var声明的变量 和 function声明的函数都集中定义到作用域最顶端, 但是赋值会留在原地!
2. 优先级 :
变量 > 函数
!! 特殊 : 直接量声明的函数当做变量处理
五 . 方法重载 :
1 . 规则 :
相同的函数名,根据传入的实参的不同来判断自动选择相应的函数去执行,但是js中不支持,写在后面的同名函数会覆盖前面是的函数 ;
2 . js中的重载 :
js中,在函数内部自带 ( 不用用户创建 ) 了一个arguments对象( 类似数组对象 ) ,这个arguments类数组对象,哪怕函数没有写任何形参,他也会接住所有的实参,所以这个默认length = 0 ;
!! arguments的使用方法 :
(1)通过实参在实参列表中的下标,来获取某一个实参 : arguments [ i ];
(2)通过length判断传入了几个实参 :arguments.length ;
(3) 在函数内部,通过对传入实参的判断来实现分支操作 , 从而在函数内部实现重载 ;
数组
1. 特点 : 一个变量保存多个数据,数组都是线性排列,每个元素都有一个前驱元素,一个后继元素 ,数组中每个元素有自己的位置叫下标 ,从0开始
2 . 创建数组:2种
1 . 直接量方式:var arr=[];//空数组
var arr=[数据1,...];
2 . 构造函数方式:var arr=new Array();//空数组
var arr=new Array(数据1,...);
3、获取数组之中的元素: 数组名[i]
4、后续添加/替换元素:
数组名[i]=新数据;
如果下标处没人则为添加,如果下标处有人则为替换
5、数组具有三大不限制
1、不限制元素的类型
2、不限制元素的长度
3、不限制下标越界 (缺点)
如果获取元素时 ,下标越界 ,返回的是一个undefined
如果添加元素时 ,下标越界 ,会得到一个稀疏数组,如果我们搭配上我们学过循环去遍历获取每个元素,会得到很多很多undefined ;
问题:自己数下标,难免会数错,导致我们下标越界
6 .数组属性length :
数组中有一个唯一的属性:length
语法:数组名.length
作用:获取到数组的长度,长度是从1开始的
length 属性的三个固定套路:
1、向末尾添加元素:arr[arr.length] = 新数据;
2、获取数组的倒数第n个元素:arr[arr.length-n];
3、缩容:删除倒数n个元素:arr.length-=n;
7 . 遍历数组
往往很多情况需要拿出每个元素来进行 相同 或 相似的操作 --- 搭配上循环
遍历固定公式:
for(var i=0;i
arr[i];//当前次元素
}
DOM
1. DOM:(Document Object Model)文档对象模型:专门用于操作HTML文档的,提供了一些方法给你。
2. DOM树概念:DOM将我们的HTML看作了是一个倒挂的树状结构,但是树根不是html标签,而是document的对象
document对象:不需要我们程序员创建,由浏览器的js解释器自动创建,一个页面只有一个document树根
作用:可以通过树根找到我们想要的任何一个DOM元素/节点/对象(属性和方法)
DOM会将页面上的每个元素、属性、文本、注释等等都会被视为一个DOM元素/节点/对象
3. 查找元素:两大方面:
(1)直接通过HTML的特点去查找元素
1. 通过 ID 查找元素:
var elem=document.getElementById("id值");
特殊:
1、返回值,找到了返回当前找到DOM元素,没找到返回的一个null
2、如果出现多个相同id,只会找到第一个
3、记住控制台输出的样子,这个样子才叫做一个DOM元素/节点/对象,才可以下午去做操作
4、忘记此方法,不允许使用,id不好用,一次只能找一个元素。id留给后端用
5、其实根本不用查找,id直接可用
2. *通过 标签名 查找元素:
var elems=document/已经找到的父元素.getElementsByTagName("标签名");
特殊:
1、返回值,找到了返回一个类数组DOM集合,没找到得到空集合
2、js只能直接操作DOM元素,不能直接操作DOM集合,解决:要么下标拿到某一个,要么遍历拿到每一个。
3、不一定非要从document开始查找,如果从document去找,会找到所有的元素,可以换成我们已经找到的某个父元素
3. *通过 class 查找元素:
var elems=document/已经找到的父元素.getElementsByClassName("class名");
特殊:
1. 返回值,找到了返回一个类数组DOM集合,没找到得到空集合
2. js只能直接操作DOM元素,不能直接操作DOM集合,解决:要么下标拿到某一个,要么遍历拿到每一个。
3. 不一定非要从document开始查找,如果从document去找,会找到所有的元素,可以换成我们已经找到的某个父元素
2、*通过关系去获取元素:前提条件:必须先找到一个元素才可以使用关系
父元素: elem.parentNode; - 单个元素
子元素: elem.children; - 集合
第一个子元素: elem.firstElementChild; - 单个元素
最后一个子元素:elem.lastElementChild; - 单个元素
前一个兄弟: elem.previousElementSibling; - 单个元素
后一个兄弟: elem.nextElementSibling; - 单个元素
为什么要通过关系去找元素呢?不希望影响到别人,只希望影响到自己的关系网
4、操作元素:前提:先找到元素,才能操作元素,3方面
1. 内容:
1、*elem.innerHTML - 获取和设置开始标签到结束标签之间的内容,支持识别标签的
获取:elem.innerHTML;
设置:elem.innerHTML="新内容";
2、elem.innerText - 获取和设置开始标签到结束标签之间的纯文本,不识别标签的
获取:elem.innerText;
设置:elem.innerText="新内容";
以上两个属性都是专门为双标签准备,而有一个单标签也是可以写内容,叫做<input/>,我们如何获取?
3、input.value - 专门获取/设置input里的内容
获取:input.value;
设置:input.value="新内容";
2、属性:
获取属性值:elem.getAttribute("属性名");
设置属性值:elem.setAttribute("属性名","属性值");
简化版:
获取属性值:elem.属性名;
设置属性值:elem.属性名="属性值";
简化版的缺点:
1、class必须写为className - ES6(2015年)class变成了一个关键字
2、不能操作自定义属性
3、样式:
使用样式的方式:3种
1、*内联样式
2、内部样式表
3、外部样式表 - 一阶段做开发用的都是外部样式表
二阶段我们就要用js来操作【内联样式】
1、不会牵一发动全身
2、优先级最高
获取样式:elem.style.css属性名;
设置样式:elem.style.css属性名="css属性值";
特殊点:
1、css属性名,有横线的地方,去掉横线,变为小驼峰命名法
border-radius ----- borderRadius
2、小缺陷:获取时,我们只能获取到内联样式,因为我们目前学的就是内联样式的操作
4、绑定事件:
elem.on事件名=function(){
操作;
*****关键字this - 这个
如果单个元素绑定事件,this->这个元素
如果多个元素绑定事件,this->当前触发事件元素
}
一切的获取,往往都是为了判断
一切的设置,可以说是添加也可以说是修改