js第一周学习笔记
day1 js基础
1、javaScript定义:是一种运行在浏览器的解释弱类型的面向对象脚本语言。
解释型:不需要编译直接运行,遇到错误停止。
编译型:先编译后运行,编译出错则不运行。
弱类型:变量的保存可以是随意的数据类型由数据决定,比较自由
强类型:变量保存的类型数据,由数据类型决定,比如java
js的特点:可以由一切的编译软件进行编写。
2、怎么使用js:
1、在页面中:
<script>遍写自己的js</script>
2、外部引入:
<script src="js路径">此处不可写内容</script>
3、一般开发的时候都会使用外部引入。
4、输出方式:打桩输出,方便检查错误。
2.4.1、控制台输出:
console.log();
2.4.2、页面输出:此方法会改写整个页面,不常使用
document.Write();。
2.4.3、提示框输出:此方法有时候会卡住整个页面。
alert();
3、变量:创建后可更改。
1创建方法:
var a=值;
2使用:
当页面中需要重复调用某个值时,便会将该值存储在变量中,之后直接使用变量名。
3特殊:
1、变量名不可随意,不能以数字开头,建议使用小驼峰命名法或者是中间用下划线,命名尽量见名知意。
2、变量明不能是关键字,否则会被隐式转换。
3、变量被创建后可以不赋值此时存储的是undefined。
4、变量名尽量不重复。
5、创建多个变量时:var 变量名1,变量名2,变量名3....;
4、常量:创建后不可更改
创建方法:
const 常量名=值;
关键字:const;
其他的用法与变量一致。
5、数据类型:
原始数据类型:
number:数字类型,取值为无数个,数字直接书写,显示的颜色为蓝色;
string:字符串类型,取值为无数个,必须加''或者"" , 页面上取到的所有数据的类型都是字符串类型
boolean:布尔类型,取值为true和false,用作判定
null:空,唯一的作用就是释放变量,释放内存,节省存储空间。
undefined:取值为undefined,屁作用没有。
引入数据类型:有是11个,有自己的属性和方法。
6、运算符:
1、算数运算符:+、-、 *、 /、 % :
带有隐式转换,转换为数字类型;
%:作用:
1、取余
2、判定奇偶数(i%2==0或1)
3、取任意数字的后几位。
比较特殊的:
+运算符在遇到字符串的时候会转变为字符串拼接。
2、比较运算符:>、<、==、!=、===、!== :
带有隐式转换:转换为数字
结果是一个布尔值
特殊:
1、如果参与比较中含有字符串则会转换成字符串的编码进行比较:
数字<大写<小写<汉字
2、NaN参与任何比较运算的结果都是false,带来了一个问题,那就是如何判断它是不是一个NaN。
解决方法:!isNaN(x)结果是布尔值,true就是一个有效数字,false就是一个无效数字。
3、undefined==null---->true这个问题的解决方法:
使用===,因为===全等不带有隐式转换,所以undefined===null---->false。
3、赋值运算符:=、+=、-+、*=、/=、%= :
1、=为赋值,var a=1;将右边的数据1保存在左边的变量a中。
2、后面5个为升级写法,先做相应的运算后赋值,例如:
a+=1;等价于a=a+1;
4、逻辑运算:&&(并且)、||(或者)、!(非):
  1、结果是一个`布尔值`<br>
  2、`&&`运算`满足所有的条件结果为true`,只要有`其中一个不满足`结果就为`false`。<br>
  3、`||`运算`满足其中一个条件结果就为true`,`都不满足`时才为`false`。<br>
  4、`!`运算就是`颠倒布尔值`。<br>
5、自增运算:++、-- :
1、i++等价于i+=1等价于i=i+1;
2、++每次固定+1,--每次固定-1;
3、+=累加,每次加几由程序员决定
4、++i和i++的区别:(笔试题)
1、单独使用时两者没有区别;
2、参与了其他表达式时,变量始终都会+1,但是两者的返回值不同:
++i返回的是加过之后的新值
i++返回的是加之前的旧值
6、位运算:
1、左移运算:m<<n,m向左移几位,m2的n次方位
2、左移运算:m>>n,m向右移几位,m2的n次方位
存在极大限制:底数只能为2
day2 分支结构
1、程序流程控制的3种结构:
1、顺序结构:默认,按顺序执行。
2、分支结构:通过条件判断,选择需要执行的代码段。
3、循环结构:条件判断,选择需要重复执行的代码段。
2、分支结构(3)种:
1、if语句(3种情况):
1、一个条件一件事,满足做第一个,不满足就不做:
if(条件){操作}
2、一个条件两件事,满足做第一个,不满足做第二个:
if(条件){
操作1
}else{
操作2
}
3、多个条件多件事:
if(条件1){
操作1
}else if(条件2){
操作2
}else if(条件3){
操作3
}....
else{
默认操作
}
注意:
1、else if(){}写几遍由程序员决定。
2、else可以省略,但是不推荐,因为条件都不满足则不能做操作。
3、分支走了一条路就不会走其他的路了。
2、switch...case分支:
语法:
switch(变量/表达式){
case 值1:
操作1;
break;
case 值1:
操作1;
break;
case 值1:
操作1;
break;
......
default:
默认操作;
}
1、问题:只要满足一个case后,会将后续的所有操作全部做完
解决方法:每个case之后加上一个break(default之后不用加,并且中间多个条件做的操作相同时可省略)
2、case作比较时不带隐式转换
3、default不建议省略,
****面试题:
if和switchd的区别:
1、switch...case:优点:执行效率高,速度快(做的是等值比较而不是范围比较)
缺点:必须知道最后的结果是什么才可以使用。
2、if..else:优点:可以做范围判断
缺点:执行效率低,速度慢
建议:代码完成后,要做代码优化,少用if...else。
3、三目运算:
语法:
条件1?操作1:条件2?操作2:条件3?操作3.....:默认操作。
注意:
1、最后的默认操作不能省略。
2、如果操作复杂不能使用三目运算,如果操作有多语句,更推荐使用swich和if语句
3、强制数据类型转换
*****js从页面上获取到的所有元素都是字符串类型
1、转字符串(2种方法):
1、x.toString();不能是undefined和null,因为他俩不是对象
2、var string=String(x);万能的,完全等效于隐式转换,还不如 +"" ;(此方法基本不用)
2、***转数字3种方法***:
1、parseInt(str):专门将字符串转为数字
执行原理:从左到右依次读取转换每个字符,碰到非数字字符停止转换,如果一开始就不认识就为NaN,此方法不认识小数点。
2、parseFloat(str):专门用于将字符串转为小数
执行原理:几乎和parseInt()一样,只认第一个小数点
3、Number(x):万能的,任何类型都可以转换成数字,不手动使用,还不如 -、\*、/
3、转布尔:
Boolean(x):万能的,任何数据类型都可以转换,不手动使用,还不如!!
转换之后为false的情况:0,null,undefined,NaN,false,"" 其余都是true。
day3循环结构while、for、do...while
1、循环结构:反复执行相同或者相似的操作
循环三要素:
1、循环条件:开始~结束,循环次数
2、循环体:做的操作是什么
3、循环变量:记录着我们当前的循环在哪一次,以及会不断地变化
2、三种循环:
1、while循环:
语法:
var循环变量=几;
while(循环条件){
循环体;
循环变量变化;
}
执行原理:首先创造出循环变量,判断循环条件,如果条件满足,则做一次循环体操作,并不会退出循环,而会回头再次判断循环条件满不满足,如果满足,则做一次循环体操作...直到条件不满足,才会退出循环。
它的特殊之处:
1、不确定循环次数的时候需要使用死循环:默认永远不会停下的循环
语法:
while(true){
循环体;
}
2、 break:停下死循环,退出整个循环,break通常搭配死循环
continue:退出本次循环,下一次依旧会执行
2、for循环:比while循环更简洁
语法:
for(var 循环变量=几;循环条件;循环变量变化){
循环体;
}
死循环:for(;;){
循环体;
}
面试题:while和for的区别:
在原理上几乎没有区别;
一般来说不确定循环次数的时候会使用while循环的死循环,而确定了循环次数以后使用for循环
3、do...while循环:
语法:
var 循环变量=几;
do{
循环体;
循环变量的变化;
}while(条件)
while和do...while的区别:
区别只有第一次,while循环第一次条件不满足时就不进行循环操作,而do...while循环就算第一次的条件不满足也会做一次循环操作
4、函数的基础——函数在js中的地位极高
1、概念:
function也叫函数也叫方法,先预定好,可以反复使用的代码段
2、使用方法:
定义好以后需要调用才能使用
定义:
function 函数(){
函数体(代码段);
}
调用函数:
1、在js中写 函数名();
2、在html中绑定事件
3、何时使用函数:
1、不希望直接打开页面触发
2、希望用户触发提升用户体验
3、以后每一个独立的功能定义好以后都要封装在一个函数中
4、与之前学过的函数不太一样
5、带参函数的写法:2步:
1、创建出带有形参的函数——形参:其实就是一个变量,只不过不需要加var,而且不需要赋值,所以称之为形式参数,简称形参
语法:
function 函数名(形参1,形参2,形参3....){
函数体(代码段);
}
2、使用带有形参的函数时,必须传入实参——实际参数,就是所传递的值
语法:
函数名(实参1,实参2,实参3......);
注意:传参时的参数顺序是不能乱的,必须和形参的顺序一一对应,数量也要对应。
总结:
不带参的函数用于执行一些固定操作
带参函数可以根据我们传入的实参的不同,做略微不同的操作。
总结:
循环也能反复执行,函数也能反复执行,他们的区别在哪里?
1、循环:几乎是一瞬间就完成了
2、函数:需要调用才能执行
day4函数(函数名与变量名不能冲突)
1、创建方式:2种
1、声明方式创建函数
function 函数名(){
操作;
return 结果;
}
2、直接量方式:
var 函数名=function(形参列表){
操作;
return 返回值;
}
2、调用:
函数名(实参列表);
3、作用域:
1、全局作用域:全局变量和全局函数,在页面上的任何地方都可以使用
2、函数作用域:局部变量和局部函数,只有在当前函数内可用
带来了变量使用规则,先找局部本身后找全局中有没有,都没有就会报错
特殊点(缺点):
1、千万不能在函数中对未声明的变量直接赋值,会造成全局污染
全局污染:全局中没有,但被函数的作用域添加上
2、局部可以使用全局,但是全局不能使用局部、
解决方法:在函数体的最后加上return 结果,但是此方法只是让函数返回一个结果,并未将此结果保存起来,所以在函数作用域以外要声明一个变量,并将返回值赋值给此变量:var 变量名=function(实参列表);需不需要加return看程序员个人,如果需要拿着函数的结果去做其他操作就加上,就算不加上它也有一个默认的返回值undefined。前辈们提供的一些方法大部分都加有return。
function(a,b){
函数体;
return a*b;
}
var result=function(1,2);
4、声明提前(笔试题)
规矩:在程序正式执行之前,var声明的变量和function声明的函数都会在我们看不到的情况下被集中定义在了当前作用域的顶部并且变量要在函数之前,赋值则留在了原地
强调:
声明方式function(){}创建的函数会整体的全部提前
直接量创建的函数var a=function(){}则会只有之前的var a提前,之后的a=function(){}则留在了原地
何时使用:永远不会自己使用,干扰我们的判断,只会在笔试题中出现
只要我们遵守变量名和函数名尽量不要重复和先创建后使用的规则,我们在开发过程中就不会遇到此情况
八道例题:
最基本的声明提前
console.log(a);//undefined
var a=1;
console.log(a);//1
最基本的声明提前
f1();
function f1(){
console.log("我是f1函数")
}
最基本的声明提前
f1();
var f1=function(){
console.log("我是f1函数")
}
鄙视题1:
var f1=1;
function f1(){
console.log("我是f1函数")
}
f1();//?
鄙视题2:
var a=10;
function f1(){
console.log(a);//?
var a=20;
console.log(a);//?
}
f1();
console.log(a);//?
鄙视题3:
function fn(){
console.log(1)
}
fn();//?
function fn(){
console.log(2)
}
fn();//?
var fn=100;
fn();//?
鄙视题4:
function fn(){
console.log(1);
}
fn();//?
var fn=100;
var fn=function(){
console.log(2)
}
fn();//?
鄙视题5:
var fn=function(){
console.log(1);
}
fn();//?
function fn(){
console.log(2);
}
fn();//?
var fn=100;
function fn(){
console.log(3);
}
fn();//?
鄙视题6:
function fn(){
console.log(1);
}
fn();//3
var fn=function(){
console.log(2);
}
function fn(){
console.log(3);
}
var fn=function(){
console.log(4);
}
fn();//4
鄙视题7:
function f1(){
console.log(a);//?
a=20;
console.log(a);//?
}
console.log(a);//?
var a=10;
f1();
console.log(a);//?
a=100;
console.log(a);//?
鄙视题8:
function f1(a){
console.log(a);//?
a=20;
console.log(a);//?
}
console.log(a);//?
var a=10;
f1();
console.log(a);//?
a=100;
console.log(a);//?
5、函数的重载:
含义:相同的函数名,根据传入的实参的不同,自动选择对应的函数去执行,但是js不支持,函数名如果函数名重复了,后面的肯定会覆盖前面的
目的:减轻程序员的压力,记住一个方法可以执行很多的操作
解决:在函数内部自带有一个arguments是、的对象(类数组对象:不需要我们去创建就能使用的数组)哪怕没有写任何的参数,他也可以接收所有的实参
固定套路:
1、通过固定下标去获取输入的某一个实参:arguments[i]——i从0开始,最大为arguments.length-1
2、通过length去获取到底传入了几个实参:arguments.length,通过判断传入的实参不同,在内部去写判断,从而变相去实现重载
function zwjs(name){
return "我的名字叫"+name;
}
function zwjs(name,age){
return "我的名字叫"+name+",今年"+age+"岁";
}
function zwjs(name,age,hobby){
return name+"今年"+age+"岁,喜欢"+hobby;
}
console.log(zwjs("袍哥"));
function f1(){
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
console.log(arguments[3]);
console.log(arguments[4]);
console.log(arguments.length);
}
f1(4,"袍哥");
function zwjs(){
if(arguments.length==1){
return "我的名字叫"+arguments[0];
}else if(arguments.length==2){
return "我的名字叫"+arguments[0]+",今年"+arguments[1]+"岁";;
}else if(arguments.length==3){
return arguments[0]+"今年"+arguments[1]+"岁,喜欢"+arguments[2];
}
}
console.log(zwjs("袍哥",18,"吃饭"));
创建一个方法,传入一个实参的时候求平方,传入两个实参的时候求和
function calc(){
console.log(arguments);
if(arguments.length==1){
return arguments[0]*arguments[0];
}else if(arguments.length==2){
return arguments[0]+arguments[1];
}
}
console.log(calc(8));
console.log(calc(8,8));
6、数组基础——很重要并且也有点难度
1、数组的特点:
数组都是线性排列的,除了第一个元素,其余的所有元素都有前驱元素;除了最后一个元素,其余的所有元素都有后继元素。
每个元素都有一个自己的位置,称之为下标,下标都是从0开始的,到最大长度-1结束
2、创建数组(2种方式):
1、直接量方式:
var arr=[];//空数组
var arr=[数据1,数据2,数据3...];
2、构造函数方式:
var arr=new Arr()//空数组
var arr=new Arr(数据1,数据2,.....);
3、获取数组之中的元素
数组名[i];
4、后继的添加/替换元素:
数组名[i]=新数据;
如果下标处没有元素则为添加元素,下标处有则为替换元素
5、数组的三大不限制:
1、不限制元素类型
2、不限制元素的长度
3、不限制下标越界——不是一个好东西
如果获取元素时,下标越界,返回的是一个undefined
如果添加元素时,下标越界,会得到一个稀疏数组,如果搭配上循环去遍历数组每个元素时,会得到很多undefined
6、我们有时会遇到自己数错下标的问题,导致我们的下标越界,如何解决呢?
解决方法:数组中有一个唯一的属性:length
作用:获取到数组长度,长度是从1开始的与下标的开始有所不同
语法:
数组名.length
通过length去添加元素
var arr=[数据1,数据2...];
arr[arr.length]=新的数据;
6、遍历数组——很重要
含义:往往很多情况,我们不会去拿出某个元素来使用,而是拿出所有元素进行相同或者相似的操作,此时就要搭配上循环来进行此操作,这就叫做遍历数组
固定公式:
for(var i=0;i<arr.length;i++){
arr[i]; //拿到当前每次循环的元素
}
day5DOM基础
1、DOM:Document Object Model,文档对象模型,专门用于操作HTML文档,提供了一些方法
2、DOM树概念:
DOM将我们的HTML看做是一棵倒挂的树,树根不是HTML而是我们的Document对象
document对象:不需要程序员创建,由浏览器的js解释器自动创建,一个页面只有一个document对象
作用:可以通过树根找到我们想要的任何一个DOM元素/节点/对象(属性和方法)
DOM会将页面上的每个元素、属性、文本、注释等都被视为一个DOM元素/节点/对象
3、查找元素:
直接通过HTML特点去查找元素
1、通过ID查找元素
var elem=document.getElementById("id名");
特殊:
1、返回值:找到了返回当前找到的DOM元素,没找到返回null;
2、如果有多个相同的ID名,则只会找到第一个
3、记住控制台输出的样子,这个样子才叫一个DOM元素/对象/节点,这样才可以进行接下来的操作
4、忘记这个获取的方法,通过id一次只能获取到一个元素,不方便我们接下来的操作,所以通常id留给后端用
5、其实根本不需要用id去查找,id可以直接使用
2、通过标签名去查找元素:
var elems=document.getElementsByTagName("标签名");
特点:
1、返回值:找到返回的是一个类数组的DOM集合,没找到是空集合
2、***js只能操作DOM元素,不能直接操作DOM集合
解决该问题:要么通过下标拿出某个元素,要么通过遍历获取所有元素
3、不一定非要从document开始查找,如果从document开始去找,会找到所有元素,可以换成我们已经找到的某个元素
3、通过关系去获取元素:
父元素:elem.parentNode;结果是单个元素
子元素:elem.children;结果是个集合
第一个子元素:elem.firstElemntChild;结果是单个元素
最后一个子元素:elem.lastElemntChild;结果是单个元素
前一个元素:elem.previousElementSibling;结果是单个元素
后一个元素:elem.nextElementSibling;结果是单个元素
通过关系去获取元素的原因:不希望影响其他元素,只希望影响到自己的关系网
4、操作元素(3方面)
前提:先找到元素,之后才能进行操作
1、内容和文本
1、内容:elem.innerHTML——获取和设置开始标签和结束标签之间的内容,支持识别标签
获取:
elem.innerHTML;
设置:
elem.innerHTML="新内容";
2、文本:elem.innerText——获取和设置开始标签和结束标签之间的纯文本,不能识别标签
获取
elem.innerText;
设置:
elem.innerText="新内容";
以上两个属性都是专门为双标签准备的,而有一个单标签<input/>也是可以写内容的
input.value——专门获取/设置input里的内容
获取
input.value;
设置:
input.value="新内容";
2、属性:
获取属性值:
//原生写法:
elem.getAttribute("属性名");
//简化写法:
elem.属性名;
设置属性值:
//原生写法:
elem.setAttribute("属性名","属性值");
//简化写法:
elem.属性名="属性值";
简化写法的缺点:
1、class必须写成className——在ES6以后将class变为了一个关键字,故而不能直接使用
2、不能直接操作关键字
3、样式:
1、使用样式的方法(三种):
1、内联样式——现阶段学的js操作的就是内联样式
2、内部样式表
3、外部样式表
使用js操作内联样式的好处:
1、不会牵一发而动全身
2、内联样式的优先级最高
2、获取和设置样式:
获取
elem.style.css属性名;
设置
elem.style.css属性名="css属性值";
特殊点:
1、css属性名:有横线的地方去掉横线,后面的首字母大写变为小驼峰命名法
border-radius——>borderRadius
2、小缺陷:获取时,我们只能获取到内联样式,因为现阶段学的是内联样式的操作
4、绑定事件:
elem.on事件名=function(){
操作;
关键字this
如果单个元素绑定,this就是这个元素;
如果多个元素绑定事件,this就是当前触发事件的元素
}
总结:
一切的获取往往都是为了判断
一切的设置,可以说是添加亦可以说是修改