1. JS相关常识
1.1 JS的一些语法
js是比较随意的一门语言,很多老式浏览器都是支持ES5规范,而JS的ES6规范很多需要转化成ES5规范。
在ES5规范中,定义变量都用var来定义,但是在ES6规范中,还新增了let,const。
其中,var其实是可以代替let和const的,但是有时会引起不必要的错误,比如用var定义常量时常量可以被修改,比如在for循环中如果用var定义循环变量i会导致其他地方也可以用i,所以有了ES6规范。
let,定义局部变量,有以下几个特点
- let拥有块级作用域,一个{}就是一个作用域
- let在其作用域下面不存在变量提升
- let在其作用域中不能被重复声明(函数作用域和块级作用域)
const,定义常量,有以下几个特点
- 一旦声明,其值就不可以更改,如果你非得修改变量的值,js不会报错,只是默默表示失败(不起作用)
- const的作用域与let相同,只在声明所在的块级作用域内有效,并且也是和let一样不可以重复进行声明。
1.2 调试的一些常识
在浏览器的console可以输入相关指令或者直接输入相关JS代码均可调试,在source里可以对html打断点,逐一调试。
1.3 代码块
使用{ }表示一组代码语句,要么同时执行,要么都不执行
{
console.log('猪');
Alert('我不是猪');
}
1.4 常用自带函数
//弹出一个可以输入文本的提示框,用户可以输入一段字符串,该字符串可以用在后端代码
//prompt()
var source=prompt('请输入小明的期末成绩');
alert(source);
//
2. JS的数据类型
2.1 常用数据类型
-
number
js不区分小数和整数,均使用number,其中需要注意的是:
NAN:not a number (表示不是数字,用于判断)
Infinity:表示无限大的数,已经超出了js的范围 -
字符串类型
例如’a,b,c’,'大’等等 -
布尔值
true,false -
逻辑运算
与:&&
或:||
非:! -
比较运算符
= 是赋值
== 是比较,但是不严谨,即类型可以不一样,值一样就好,比如字符串类型与数字类型、布尔类型;数字与布尔类型等等
=== 绝对等于,类型必须一样,值必须一样
!= 是==的不等形式,与其一样,不管类型,只管值
!== 是===的不等形式既管值也管类型
须知:
1.NAN与所有数值都不等,包括自己,只能通过方法isNAN()来判断是否为NAN
2.尽量避免浮点数运算,会有误差,比如1/3===1-2/3,结果是false
- null和Undefine
null表示为空
undefine表示未定义 - 数组
一系列对象的集合,比如
var arr=[1,2,'s',true];
//或者是
new Array(1,2,'abc');
- 对象
比如
//对象定义
var Person={
name:'小猪',
birth:2000,
age:function(){
var t=newDate().getFullYear();
return t-this.birth;
}
}
//对象取某个属性值
var x=Person.name;
2.2 严格检查模式
在<script>
的第一行加上'use strict'
,注意要在第一行,严格检查模式的作用是为了以新标准来检查是否出现一些无法报错的错误,严禁
2.3 常用数据类型的用法
2.3.1 字符串
1.正常字符我们需要用单引号或者双引号包裹
2.注意转义字符
3.多行字符串的编写,使用此符号包裹 ``,此符号是Tab键的上面一个
4.支持模板化字符串,即使用 '${ }'的形式,例如
let name='xiaoming';
let message='你好呀,${name}';
5.获取字符串长度
var str='abhsgj';
console.log(str.length);
6.字符串的可变性,是不可变的,举个例子
var t='abcd';
console.log(t[0]);//输出答案是a
//现在对其t[0]的值进行改变
t[0]='b';//发生错误,不可以改变
7.大小写转换
var str='abhsgj';
str.touppercase();//这里转大写
str.tolowercase();//这里转小写
8.取下标
//如果有重复的内容,则索引是第一个出现的位置
var str='abhsgj';
str.indexof('a');//输出为0,即下标是0
9.截取字符串:原则左包右不包
var str='abhsgj';
str.substring(1);//从第一个字符截取到最后一个字符,即bhsgj
str.substring(1,3);//从第一个字符截取到第三个字符,第三个不要,即bh
2.3.2 数组
首先来定义一个数组方便下面使用
var arr=[1,2,3,4,5,6];//下标从0开始,为0,1,2,3,4,5
//或者
var arr=new Array();
1.长度
arr.length(),给arr.length赋值,会改变数组的长度,多的部分为空,如果赋值过小,则会丢失原始数组里的一部分
小知识点:在某个数组后面添加一个元素可以这样添加:数组名[数组名.length]=xx
,相当于往后面加了一个下标
2.找下标,即下标索引
indexof()
arr.indexof(2);//结果为1,即下标为1
3.slice(),截取数组的一部分,返回一个新数组
-可以用来从数组中提取元素
-该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回
-参数:
1.截取开始的位置的索引,包含开始索引
2.截取结束位置的索引,不包含结束索引(这个参数可以不写,此时会截取到从开始索引后的所有元素)
索引可以传递负数,如果传递一个负数,则从后往前计算
arr.alice(1);//结果是[2,3,4,5,6],一样从下标为1的地方开始截取
4.push(),pop(),对数组末尾元素进行操作
//压入数组末尾
arr.push('a');//输出=>[1,2,3,4,5,6,'a']
//弹出数组末尾元素
arr.pop();//输出=>[1,2,3,4,5,6]
5.unshift(),shift(),对数组头部元素进行操作
//压入数组头部
arr.unshift(9);//输出=>[9,1,2,3,4,5,6]
//弹出数组头部元素
arr.shift();//输出=>[1,2,3,4,5,6]
6.排序,sort()
//[1,3,2]=>[1,2,3]
7.元素反转,reverse()
[1,2,3]=>[3,2,1]
8.数组拼接,concat()
var t=[1,2,3];
arr.concat('a','b','c');//输出=>[1,2,3,'a','b','c']
9.连接符,join(),连接成字符串
arr.join('-');//输出=>"1-2-3"
10.多维数组
var t=[[1,2],[3,4],[5,6]];
t[1][1];//输出=>4,按下标来看的
11.splice(),删除数组中的指定元素,并向数组添加新元素
-删除数组中的指定元素
-使用splice()会影响到原数组,会将指定元素从原数组中删除,并将被删除的元素作为返回值返回
-参数:第一个表示开始位置的索引,第二个参数表示删除元素的数量,第三个及以后所有的元素会自动插入到开始位置索引的前面,相当于替换
var arr=[1,2,3,4,5,6];//下标从0开始,为0,1,2,3,4,5
var result=arr.splice(0,2);
console.log(arr);//输出原数组=>arr=[3,4,5,6]
console.log(result);//输出删除的内容=>[1,2]
//第二个功能,向数组添加新元素
var arr=[1,2,3,4,5,6];//下标从0开始,为0,1,2,3,4,5
var result=arr.splice(0,2,3);//删除索引从0开始的2个元素,然后将后面需添加的元素3加入原数组
console.log(arr);//输出原数组=>arr=[3,3,4,5,6]
2.3.3 对象
1.对象的固定形式
var 对象={
属性名:属性值,
属性名:属性值,
......
};
2.如果使用一个对象不存在的某个属性,不会报错,只会
undefined
3.动态的删除属性,delete
delete Person.name;
4.动态的增加,直接给新的属性添加值
//属性haha是Person对象中所没有的属性,这句话给Person添加了一个haha属性,还给haha属性提供了初始值
Person.haha='haha';
Person.sayhello=function(){console.log('hello');};//创建函数类型的属性到对象,这个时候这个属性(函数)就是方法了
5.判断一个属性是否在一个对象中
注意:如果这个对象是继承的,继承的属性也会在这里面,所以一个属性是否在一个对象中并不一定是说一个属性是这个对象本身所有的
//模板
'xx' in Person;//这个判断输出是布尔类型的值
6.判断一个属性是否是这个对象本身所有的,hasOwnProperty()
Person.hasOwnProperty('age');//里面是属性名,输出也是布尔类型的值
2.3.3.1 原型概念
Javascript规定,每一个函数都有一个prototype
对象属性,指向另一个对象(原型链上面的)。
prototype
(对象属性)的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变(公用)的属性和方法,直接定义在prototype
对象属性上。
prototype
就是调用构造函数所创建的那个实例对象的原型(proto)。
prototype
可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。
3.3.3.2 原型链
实例对象与原型之间的连接,叫做原型链。proto( 隐式连接 )
JS在创建对象的时候,都有一个叫做proto的内置属性,用于指向创建它的函数对象的原型对象prototype。
内部原型(proto)和构造器的原型(prototype)
1、每个对象都有一个proto属性,原型链上的对象正是依靠这个属性连结在一起
2、作为一个对象,当你访问其中的一个属性或方法的时候,如果这个对象中没有这个方法或属性,那么Javascript引擎将会访问这个对象的proto属性所指向上一个对象,并在那个对象中查找指定的方法或属性,如果不能找到,那就会继续通过那个对象的proto属性指向的对象进行向上查找直到这个链表结束。
3.3.3.3 对原型添加属性或者函数
function Person(name,age){
this.name = name;
this.age = age;
}
//对一个构造函数的原型添加函数
Person.prototype.sayHello=function(){
console.log(this.name + "say hello");
}
//对一个构造函数的原型添加属性
Person.prototype.Hello="你好";
var girl = new Person("bella",23);
var boy = new Person("alex",23);
console.log(girl.name); //bella
console.log(boy.name); //alex
//比较两个对象引用的是否是同一个原型中的函数和属性
console.log(girl.sayHello === boy.sayHello); //true
console.log(girl.Hello === boy.Hello); //true
问题:如果原型中的某属性和某方法和一个以该原型创建的对象中的某属性和某方法名字相同,怎么办?此对象中的属性和方法会覆盖掉原型中名称相同的属性和方法,但是原型中本身所有的方法不会被覆盖
3.3.3.4 浅谈constructor
在 Javascript 语言中,constructor 属性是专门为 function 而设计的,它存在于每一个 function 的prototype 属性中。这个 constructor 保存了指向 function 的一个引用。
function Person() {
}
var p = new Person()
console.log(Person.prototype); // Object{}
console.log(p.prototype); // undifined
console.log(p.constructor); //function Person(){}
//此处的p是通过 Person函数构造出来的,所以p的constructor属性指向Person
console.log(Person.constructor); //function Function(){}
//之前提过,每个函数其实是通过new Function()构造的
console.log({}.constructor); // function Object(){}
//每个对象都是通过new Object()构造的
console.log(Object.constructor); // function Function() {}
//Object也是一个函数,它是Function()构造的
console.log([].constructor); //function Array(){}
//数组也是一个函数,它是Array()构造的
3.3.3.5 对象的属性:__proto__
JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__
的内置属性,用于指向创建它的构造函数的原型对象。
var obj = {};
var obj = new Object();//此处等价于
console.log(obj.__proto__ === Object.prototype);//true
解释:obj是通过new Object 构造出来的一个对象,那我们Object的原型对象就是Object.prototype,在Object下面构造出来的所有对象,都有一个__proto__ 指向它的原型,我们称这个为原型链
3.3.3.6 举例练习
function Person(){
}
var person1=new Person();
console.log(person1.__proto__==Person.prototype);//true
console.log(person1.constructor==Person);//true
console.log(Person.__proto__);//f()
console.log(Person.prototype.constructor==Person);//true
console.log(person1.__proto__.constructor==Person);//true
console.log(Person.prototype);//Object
2.4 强制类型转换
2.4.1 强制转换为string类型
- 使用方法tostring();
这个可以由number,布尔,null类型转换为字符串,但是NAN,undefine不可以 - 使用函数String();
这个什么都可以,包括上面不能转换的,此函数的使用就是强行加个" "
2.4.2 强制转换为number类型
- 使用函数Number();
此函数用来string类型(要纯数字的sting类型)、布尔类型、null等 - 使用函数parseInt(),专门用来取整数;
专门用来转换string类型的函数,可以把一个string类型的字符串中的数字提取出来(从前往后,中间有数字仍然算作是字符串的一部分;如果第一个就是字符,那么也提取不出来数字),比如:
var a='2sa3set';
b=parseInt(a);
console.log(b);//结果=>2
- 使用函数parseFloat(),专门用来取小数,用法和上面parseInt()一样
2.4.3 强制转化为boolean类型
- 使用Boolean()函数
结论:除了数字0、NAN、字符串空串、null、undefined,转化是false,其他全是true(包括对象也是true)
2.5 其他进制的数字
- 二进制
以0b
开头,比如0b10
,但是不是所有浏览器都支持 - 八进制
以0
开头,比如026
- 十六进制
以0x
开头,比如0x6dcf
如何转化为其他进制?
使用parseInt(x,y)
,x
是要转化的值,y
表示转化成的进制,比如y=10,8,16,2
,就表示转化为十进制,八进制,十六进制,二进制
2.6 使用Unicode字符输出
1.控制台输出,在Unicode代表的十六进制前加上\u
即可,比如\u2620
,输出:
console.log('\u2620');
2.在网页如何输出呢?
在前面加上&#
,注意这个时候Unicode要转化成十进制,举例:
<h>☠</h>//9760是十进制,其Unicode十六进制的为2620,就是上面一个例子的骷髅头
3. 流程控制语句
3.1 if判断
//和java的if一样
if(){
...
}
else if
{
...
}
else
{
...
}
......
3.2 循环
//while循环
while(){}
//for循环
for(let i=0;i<100;i++){}
//do while循环
do{}while()
//forEach()对数组中的每一个元素使用一个方法,只是适用于遍历数组,不可以遍历对象
//forEach(function(value,index,array){ });
//这个方法支持IE8及以上是浏览器
//forEach方法中的function回调(回调函数指的是不是自己调的函数,这里是浏览器调用的)有三个参数:
//第一个参数是遍历的数组内容,
//第二个参数是对应的数组索引,
//第三个参数是数组本身
var myArry =[1,2,3,4];
myArry.desc ='four';
myArry.forEach((value,index,arr)=>{
console.log(value);});
//输出
//1
//2
//3
//4
//for(var value in xx){}
//循环遍历对象的key,是键值对前面的那一个哦
//一般不推荐遍历数组,因为for in遍历后的不能保证顺序,而且原型链上的属性也会被遍历到,因此一般常用来遍历非数组的对象并且使用hasOwnProperty()方法去过滤掉原型链上的属性
//遍历出的结果是下标和里面的属性
var myArry =[1,2,3,4];
myArry.desc ='four';
for(var value in myArry){ //循环key
console.log(value)
}
//"0"
//"1"
//"2"
//"3"
//"desc" 注意这里添加上去的属性也被遍历出来了
//for(var value of myArry){}
//循环遍历对象的值,是遍历键值对后面的那一个value哦 ,与for in遍历key相反
//遍历出的结果是数组里面真正的值,常用这个
var myArry =[1,2,3,4];
myArry.desc ='four';
for(var value of myArry){
console.log(value)
}
//1
//2
//3
//4
//这是最简洁、最直接的遍历数组元素的语法
//这个方法避开了for-in循环的所有缺陷
//与forEach()不同的是,它可以正确响应break、continue和return语句
3.3 map和set
- Map类似C#的字典
//定义一个Map
var map=new Map([['tom',100],['jack',90],['haha',80]]);
//获取Map对应Key的value值
var name=map.get('tom');//输出=>100
//在map里添加key和value
map.set('admin',123456);
//在map里删除对应的key和value
map.delect('jack');
- Set是去重,无序不重合的集合
//使用一个set
var set=new Set([3,3,3,1,1,1]);//输出=>set=[3,1]
//在set出来的数组中添加一个元素
set.add(2);//注意里面添加的元素必须是不在集合里面的元素,也就是不会重复的元素
//在set出来的数组中删除一个元素
delect(1);//注意删除的元素必须是数组中含有的元素
//判断set出来的数组中是否包括某个元素
set.has(3);//输出是布尔类型的值,包括为true,不包括为false
- iterator迭代Map和Set,用上面的
for of
循环即可,后面的遍历值可以是数组,可以是map,可以是set
4. 函数和方法
4.1 定义函数
//定义函数的两种方法
function 方法名(){}
//或者
var 方法名=function(){}
//立即执行函数
//如果var 方法名=function(){}没有var 方法名,则是个匿名函数,如果要直接执行匿名函数,需要以这样格式写,里面也可以写入参数
// (function(){})();
(function(a,b){alert(a+b);})(100,200);//可以传入参数
4.2 调用问题(关于调用函数时里面输入的参数 )
注意:函数的参数和返回值都可以是任意的数据类型,包括对象,甚至传入和传出一个函数都是可以的(注意传入传出函数时,不要加括号,即(),加了括号是调用函数)
为什么有这个问题呢?js里调用函数时候,对调用函数里面的参数类型,参数:
(1)不给参数
如果需要参数但是不给参数的话,会提示NAN或Undefined
也可以自己提供一个判断,然后抛出异常,用throw
(2)给任意个参数,但是只使用函数定义的参数数量时,默认会将前面的参数与输入的参数先对应起来,如果需要得到所有的参数,则用:argument
,这是个数组,能读取输入的全部参数,但是有缺陷,argument
会包含所有参数,包括本来就需要用的函数里的参数,所以要筛选,比如argument[2]
选了下标从0开始的输入参数
有了ES6标准后,引入了rest
新特性,这个特性可以自动排除已使用的参数,比如
//定义函数
function aaa(a,b,...rest){}
//...rest是一个格式,必须放在定义函数时候参数的最后一个
//怎么使用?
aaa(1,2,3,4){}//这样的话,a=1,b=2,rest=[3,4]
4.3 参数的作用域
先讲结论:
- 内部函数可以调用外部函数的成员,而外部函数不可以访问内部函数
- 要养成规范,所有的变量定义都要放在函数头部
function qj(){
var z='x'+y;
console.log(z);
var y='y';
}//输出=>Xundefined
//为什么?因为变量y在最后面定义和赋值,但是在使用的时候,不论变量在哪定义,都会在一起作用域里先定义,赋值就不可以了
//所以,输出Xundefined表面y已定义,没有赋值
全局变量:默认所有的全局变量,都会自动绑定到window全局对象上
js实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数范围内找到,则会不停延伸查到,如果全局作用域都没有找到,则会报错引用异常。
4.4 方法
方法其实就是函数,只是换了个名称,方法是定义在对象里的,而函数不是定义在对象里的,总而言之,定义在对象内的函数成为方法,非对象内的函数还是称为函数
方法的两种定义方式:
//1.方法体直接定义在对象内
var kuangshen={
name:'da',
birth:2000,
age:function(){
var t=newDate().getFullYear();
return now-this.birth
}
}//age是方法名
//2.方法体不是直接定义在对象内
var kuangshen={
name:'da',
birth:2000,
age:getAge()
}//age是方法名
function getAge (){
var t=newDate().getFullYear();
return now-this.birth
}
4.5 this关键字
解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数是this
,this
是一个对象,这个对象我们称之为上下文对象。
根据函数的调用方式不同,this
会指向不同的对象
- 以函数的形式调用时,
this
永远指向window
- 以方法的形式调用时,
this
就是调用方法的那个对象 - 以构造函数的形式调用时,
this
是指定的那个对象 - 使用call()和apply()调用时,this是指定的那个对象
比如:
function fun(){
console.log(this);
}
//以函数的形式调用时
fun();//输出=>Object window
//以方法的形式调用时
var stu={
name:"llm",
Myfunctuon:fun
};
stu.Myfunctuon();//输出=>Object object;这后面的object表示的是stu这个对象
4.6 call()和apply()
-这两个方法都是函数对象的方法,需要通过函数对象来使用
-当对函数调用call()和apply()都会调用函数执行
Function fyn(){
Alert('猪');
}
fyn.call();//执行函数
fyn.apply();//执行函数
-在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行的this
-call()方法可以将实参在对象之后依次传递
Function fyn(a,b){
Alert(this.name);
}
var obj={name:'dada'};
fyn.call(obj,1,2);//执行函数,出来结果dada
-apply()方法需要将实参封装到一个数组中统一传递
Function fyn(a,b){
Alert(this.name);
}
var obj={name:'dada'};
fyn.call(obj,[1,2]);//执行函数,出来结果dada
-使用call()和apply()调用时,this是指定的那个对象
5. 内部对象
5.1 Date对象
//创建Date一个对象
var now=new Date();
//创建一个指定时间的对象,传入参数格式一定要注意
//日期格式: 月份/日/年 时间
var d2=new Date("12/02/2016 11:10:20");//2016.12.02 11:10:20
//基本使用
now.getFullYear();//年
now.getMonth();//月
now.getDate();//日
now.getDay();//星期几
now.getHours();//时
now.getMinutes();//分
now.getSeconds();//秒
now.getTime();//获取时间戳,用法:new Date(时间戳)
5.2 Math对象
-Math和其他对象不同,它不是一个构造函数
它属于一个工具类,不用创建对象,它里面封装了属性运算相关的属性和方法
具体的方法和属性看手册
//比如:
Math.PI;//圆周率
//制造任意区间[x,y]的随机数(整数)
Math.round(Math.random()*(y-x)+x)
5.3 Json
Json的使用或者说定义格式:
- 对象都用{ }
- 数组都用[ ]
- 所有的键值对都是key-value
常见用法:
- 将对象转化为json字符串
var t=JSON.stringify(定义的对象);
- 将json字符串解析为对象
var t=JSON.parse('一个json类型的字符串');
6. 类
这里说的类都是在ES6之后的规范
6.1 定义类和使用类
//定义类
class Student{
//类似于构造函数,也就是函数的构造器
constructor(name){this.name=name}
//定义一个类里面的函数
hello(){alert('hello')}
}
//使用类
var x=new Student('xiaoming');
6.2 类的继承
class XiaoMing extends Student{
//super()是继承父类的函数构造器
constructor(name,grade){super(name);this.grade=grade}
//定义一个类的方法
Mygrade(){alert('我是一位小学生')}
}
7. 操作BOM对象(BOM是浏览器模型)
1.Window
代表浏览器窗口
2.navigator,封装了浏览器的信息,大多数不会使用,因为会被人为修改
3.screen,代表浏览器屏幕
screen.width
screen.height
4.location(重点),代表定位,代表当前页面的URL信息
host:主机
href:当前地址
protocol:当前协议
reload:刷新,重加载
设置新地址,重定向:location.assign(‘www网站’)
5.document 当前页面的一些文档信息
比如网站标题,即 document.title
6 .history,浏览器的历史记录
history.back=>返回上一条网址
history.forward=>前进(后退之后的前进,也就是恢复原状)
8. 操作DOM(document,文档对象模型)
核心:
1.更新:更新DOM节点
2.遍历:遍历(取)DOM节点,以得到节点
3.删除:删除DOM节点
4.添加:添加DOM节点
8.1 取DOM节点
//1.根据标签取节点
//注意取出的是复数,就是数组类型的,要这样用:h1[0]等等
var h1=document.getElementByTagName('所选标签,也就是标签选择器');
//2.根据ID取节点
//注意取出的是单数,直接用就可以
var p1=document.getElementByID('给html中的元素标签定义的ID值');
//3.根据class去节点
//注意取出的是复数,就是数组类型的,要这样用:p2[0]等等
var p2=document.getElementByClassName('给html中的元素标签定义的class值');
//4.获取父节点下的所有子节点(子元素)
var t=m.Children;//m是查询出的父节点,这个是获取子元素
var u=m.childNodes;//这个是查询出所有的节点,包括文本节点,空白页算文本节点
//获取第一个子节点(子节点是包括文本节点的,如果有空格,空格也是文本节点)
var r=m.firstChild;
//获取最后一个子节点
var r=m.lastChild;
//5.获取子节点的父元素
var w=p1.ParentElement;//p1是查询出的子节点
//获取父节点
var r=m.parentNode;//此属性用来表示当前节点的父节点
//获取兄弟节点
//获取前一个兄弟节点
var r=m.previousSibling;
//获取后一个兄弟节点
var r=m.nextSibling;
//需要注意的:
//1.InnerHtml属性是用于获取元素内部HTML代码的,不适用于自结束标签
8.1.1 读取节点属性及属性值
直接使用查出的节点**.**元素名
例子:
var t=document.getElementByID('3');
t.id;//获取id属性的属性值
t.value;//获取value属性的属性值
t.name;//获取name属性的属性值
t.className;//特殊一点,不可以直接使用class,而是使用className
8.2 更新DOM节点
//p1为查询出来的节点
//1.添加或者修改文本值
p1.innerText='456';
//2.加入或者修改一段HTML代码
p1.innerHTML='<stong>123</stong>';
//3.控制style即css
//注意,style只能设置或者获取内联样式的值,也就是写在标签里面的style的值,而样式表的值不可以读取
p1.style.color='red';
//如果想读出标签的当前样式的话,不管是内联或者样式表,可以使用此方法:
//getComputedStyle()
//这个方法是window对象上的方法
//需要两个参数,第一个:要获取样式的元素;第二个:可以传递一个伪元素,一般都传null
//会返回一个对象,该对象含有该元素的所有样式,要取得某个样式的话,可以点出来
var obj=getComputedStyle(box1,null);//获取该元素当前样式下的所有样式
alert(obj.width);//获取宽度
8.3 删除DOM节点
办法1:
先找到父节点,然后删除
father.removrChild(p1);//father是父节点,p1是父节点下的子节点
办法2
不用根据父亲的id或者什么来先找到父节点,这个方便,常用
p1.parentNode.removrChild(p1);//p1是子节点,p1找到自己的父亲,然后删除自己
8.4 插入节点
我们获得了某个DOM节点,假设这个节点是空的,我们通过innerHTML就可以增加一个元素了,但是这个DOM节点以及存在元素了就不可以这样,会产生覆盖
//1.追加一个以及查询出来存在的节点成为自己的子节点
father.appendChild('x');//father是父节点,x是子节点或者说是被追加的节点
//2.举例,创建一个新的标签实现插入
//创建一个P标签
var x=document.createElement('p');//创建一个P标签
x.id='newp';//为该标签赋id
x.innerText='hello';//给值
//3.举例 万能方法
//前面是id是有该属性,如果没有怎么办?
//创建一个<script>标签即<script type="text/javascript" scr=""></script>
var y=document.createElement('script');
y.setAttribute('type','text/javascript');//里面的形式是key-value
9. 事件
9.1 事件相关
9.1.1 事件的冒泡
-事件的冒泡(Bubble)指的是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发
-在开发中大部分事件的冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡
在不希望冒泡的子代里写上
event.cancelBubble=true;//取消冒泡
9.2 一些事件小例子
9.2.1 图片切换练习
里面的图片路径根据自己所拥有的,具体的图片路径改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>爷的图片切换练习</title>
<style>
*{
margin: 0px;
padding: 0px;
}
#outer{
width: 700px;
margin: 50px auto;
padding: 10px;
background-color: silver;
text-align: center;
}
</style>
</head>
<body>
<div id="outer">
<p>一共有3张图片,当前为第1张图片</p>
<img src="img/1000009.jpg" alt="软妹子" height="100%" width="100%"/>
<button id="prev">上一张</button>
<button id="next">下一张</button>
</div>
<script>
//点击按钮切换图片
//要切换图片就是切换图片的src属性
//获取两个按钮
var prev=document.getElementById("prev");
var next=document.getElementById("next");
var img=document.getElementsByTagName("img");
//获取显示的p标签
var p=document.getElementsByTagName("p")[0];
//创建一个数组用来保存路径
var imgArr=["img/1000009.jpg","img/2030898.jpg","img/325345.jpg"];
//创建一个变量,来保存当时正在显示的图片的索引
var index=0;
//分别为两个按钮绑定单击响应函数
prev.onclick=function(){
index--;
if (index<0) {
index=imgArr.length-1;
}
img[0].src=imgArr[index];
p.innerText="一共有"+imgArr.length+"张图片,当前为第"+(index+1)+"张图片";
};
next.onclick=function(){
index++;
if (index==imgArr.length) {
index=0;
}
img[0].src=imgArr[index];
p.innerText="一共有"+imgArr.length+"张图片,当前为第"+(index+1)+"张图片";
};
//获取显示的p标签
var p=document.getElementsByTagName("p")[0];
</script>
</body>
</html>
9.2.2 拖拽(div等任意)
<script>
window.onload=function(){
//拖拽box1元素的流程:
//1.当鼠标在被拖拽元素上按下时,开始拖拽 onmouncedown
//2.当鼠标移动时被拖拽元素跟随鼠标移动 onmouncemove
//3.当鼠标松开时,被拖拽元素固定在当前位置 onmounceup
//获取box1
var box1=document.getElementById("box1");
//为box1绑定一个鼠标按下事件
box1.onmousedown=function(e){
var ol=e.clientX-box1.offsetLeft;
var ot=e.clientY-box1.offsetTop;
document.onmousemove=function(e){
var x=e.clientX-ol;
var y=e.clientY-ot;
box1.style.left=x+"px";
box1.style.top=y+"px";
}
//这样不好,如果重叠了box2,那么松开鼠标就是触发了box2的onmouseup事件了,所以我们要改为document
// box1.οnmοuseup=function(){
// document.οnmοusemοve=null;
// }
document.onmouseup=function(){
document.onmousemove=null;
//alert("2");
//取消自己的onmouseup事件
document.onmouseup=null;
}
}
}
</script>
9.2.3 滚轮事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box1{
width: 100px;
height: 100px;
background-color: red;
position:absolute;
}
</style>
<script>
//当滚轮往上滚,div变短
//当滚轮往下滚,div变长
window.onload=function(){
var box1=document.getElementById("box1");
box1.onwheel=function(e){
//判断滚轮滚动的方向
//谷歌用deltaY来判断向上向下,大于0向上滚,小于0向下滚
if (e.deltaY>0) {
box1.style.height=box1.clientHeight+10+"px";
}else{
box1.style.height=box1.clientHeight-10+"px";
}
return false;//取消浏览器的默认行为,即有滚动条时,滚动滚轮导致滚动条滚动
};
}
</script>
</head>
<body style="height: 2000px;">
<div id="box1"></div>
</body>
</html>
9.2.4 键盘事件
键盘事件一般都会绑定给一些可以获得焦点的对象或者是document
例子:键盘控制div移动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
//按左键,div向左移动,按右键向右移动,按上就上移,下就下移
window.onload=function(){
var box1=document.getElementById('box1');
var speed=10;
document.onkeydown=function(e){
//按下ctrl加快速度
if (e.ctrlKey) {
speed+=20;
}
//上下左右的KeyCode:38,40,37,39
if (e.keyCode===38) {
box1.style.top=box1.offsetTop-speed+"px";
}else if (e.keyCode===40) {
box1.style.top=box1.offsetTop+speed+"px";
}else if (e.keyCode===37) {
box1.style.left=box1.offsetLeft-speed+"px";
}else if (e.keyCode===39) {
box1.style.left=box1.offsetLeft+speed+"px";
}
}
}
</script>
</head>
<body>
<div id="box1" style="width: 100px;height: 100px;background-color: red;position: absolute;"></div>
</body>
</html>
10. 操作表单
10.1 获取和设置表单的值
表单的目的是提交,有很多种表单的形式,比如:文本框,下拉框,单选框,多选框,隐藏域,密码框…
那么如何获取和设置表单的值呢?
<form method="POST">
<span>请输入</span> <input type="text" id="1"/>
</form>
<script>
var t=document.getElementById('1');//拿到对应的节点
t.value//在控制台输入此语句可以获得输入的值
t.value=3;//可以在控制台更改输入的值
</script>
有很多表单是固定的value值,比如下拉框,单选框,多选框等等,不管有没有选中都会有对应的值,所有如何判断是否选中呢?
使用节点.checked
即可,类型是布尔类型,选中为true,未选中为false
10.2 表单提交验证及前端密码MD5加密
如果不加密的话,抓包能抓到输入的密码
比如:
所以,我们需要前台加密
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
//引入一个加密插件
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.js"></script>
</head>
<body>
<form method="POST" action="#" onsubmit="return aaa()">
<span>用户名</span> <input type="text" id="username" name="username"/>
<span>密码</span> <input type="password" id="input-password" name="password"/>
<button type="submit">提交</button>`
</form>
<script>
function aaa() {
var username=document.getElementById('username');
var inputpassword=document.getElementById('input-password');
//使用md5加密密码
inputpassword.value=md5(inputpassword.value);
return true;
}
</script>
</body>
</html>
由于inputpassword.value=md5(inputpassword.value);
所以会有以下现象,在输入密码提交后,出现很多*号,给用户体验不好,为了解决这个问题,我们用了个<input type="hidden" id="md5-password" name="password"/>
来进行转接,就不会出现上面的情况
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.js"></script>
</head>
<body>
<form method="POST" action="#" onsubmit="return aaa()">
<span>用户名</span> <input type="text" id="username" name="username"/>
<span>密码</span> <input type="password" id="input-password" />
<input type="hidden" id="md5-password" name="password"/>
<button type="submit">提交</button>
</form>
<script>
function aaa() {
var username=document.getElementById('username');
var inputpassword=document.getElementById('input-password');
var md5password=document.getElementById('md5-password');
//使用md5加密密码
//inputpassword.value=md5(inputpassword.value);
md5password.value=md5(inputpassword.value);
return true;
}
</script>
</body>
</html>
输出结果:
这是最好的简单加密方法之一
关于验证:可以通过一些事件,比如button的onclick事件,事件里面用一个函数控制,函数里面进行判断,通过节点以及取节点的值来进行逻辑判断验证,但是为了方便,一般引入一个JQuery库来进行前端验证
11. JQuery
11.1 初识jquery及公式
jquery是一个封装了很多js代码以实现各种各样功能的库,如何引入呢?有两种办法,一种是引入CDN,一种是下载jQuery到本地
//引入CDN
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
//或者下载jQuery到本地
<script src="jquery-3.5.1/jquery-3.5.1.js"></script>
使用格式:
$(selector,也就是选择器).action();
举例,使用一个a标签,点击能弹出一个警告框
<a href="" id="test-jquery">点我弹出警告框</a>
<script>
$('#test-jquery').click(function name() {
alert('我是有效的');
})
</script>
效果:
11.2 jquery选择器
css的选择器jQuery都可以使用,举三个基本选择器
$('p').click();//标签选择器
$('#id').click();//id选择器
$('.class1').click();//class选择器
其他的选择器,可以查询这个网站:https://jquery.cuishifeng.cn/,这个网站有全部的选择器
11.3 jQuery事件
11.3.1 鼠标事件小例子
需要知道的是,在加载所有元素后再使用事件,简写为$()
,在里面写一些jQuery即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#divmove{
width: 500px;
height: 500px;
border: 1px solid red;
}
</style>>
<script src="jquery-3.5.1/jquery-3.5.1.js"></script>
</head>
<body>
//里面显示坐标移动的横纵坐标
mouse:<span id="mousemove"></span>
//里面是坐标移动的区域
<div id="divmove">
</div>
<script>
//先对一片区域使用鼠标事件,然后针对鼠标事件里面的参数e,把其x,y输出到#mousemove的区域内显示
$(function () {
$('#divmove').mousemove(function (e) {
$('#mousemove').text('x:'+e.pageX+'y:'+e.pageY)
})
})
</script>
</body>
</html>
11.3.2 操作DOM元素
见下面一个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#divmove{
width: 500px;
height: 500px;
border: 1px solid red;
}
</style>
<script src="jquery-3.5.1/jquery-3.5.1.js"></script>
</head>
<body>
<ul id="test-ul">
<li class="pp">匹配</li>
<li name="66">66</li>
</ul>
<script>
$('#test-ul li[name="66"]' ).text();//获取值
$('#test-ul li[name="66"]' ).text('设置值');//设置值
$('#test-ul li[name="66"]' ).html();//获取html的值,超文本
$('#test-ul li[name="66"]' ).html('<stong>123</stong>');
//改变css的值
$('#test-ul li[name="66"]' ).css({"color":"red"});
//元素的显示和隐藏
$('#test-ul li[name="66"]' ).show();//元素的显示
$('#test-ul li[name="66"]' ).hide();//元素的隐藏
</script>
</body>
</html>
12. 正则表达式(Regular expression)
12.1 创建正则表达式的方法
//第一种
var 变量=new RegExp("正则表达式","匹配模式");
//第二种(字面量的方式)
reg=/a/i;
12.2 正则表达式语法
语法:
var 变量=new RegExp("正则表达式","匹配模式");
var reg=/正则表达式/匹配模式;
- 这创建的也是一个对象
- 举例
var reg=new RegExp("a");//这个正则表达式可以来检查一个字符串中是否含有小写字母a
//或者这样创建
reg=/a/;
var str="abcds";
//使用正则表达式
var reg.test(str);//输出=>true,true表示含有
- 在构造函数中可以传递一个匹配模式来作为第二个参数:
可以是:
i 忽略大小写(正则表达式中匹配的字符的大小写)
g 全局匹配模式 |
和[]
均表示表示或,举例:reg=/a|b|c/
、reg=[abc]
,表示检测一个字符串里是否含有a或b或c;- 创建一个正则表达式判断一个字符串是否有小写字母,
[a-z]
;[A-z]
是否含有任意字母
举例:
//检查一个字符串中是否含有abc或adc或aec
//方法1
var reg=/abc|adc|aec/;
//方法2,灵活
var reg=/a[bde]c/;
[^]
除了某某以外,也就是异或,举例,reg=/[^ab]/
,除了a,b,ab以外还有其他元素,则返回true- 量词:通过量词可以设置一个内容出现的次数,
{n}
表示出现多少次,但是量词只对它前边的一个内容起作用,如果要整体起作用,则需要用()
括起来- 如果是出现几次到几次,则
{a,b}
,指的是a到b次,而不是a或b次 - 如果是
{a,}
则表示出现a次以上 +
表示出现至少一个,相当于{1,}
*
表示0个或多个,相当于{0,}
?
表示0个或1个,相当于{0,1}
^
表示字符串中以某某开头,注意不在[]
里面,不然就是除某某以外,可以看前面的内容
$
表示字符串中的结尾.
表示任意字符- 在正则表达式中,如果为了表示某个特殊的已经有定义的字符,比如
.
则需要使用转义,比如/\./
举例:
-正则表达式中出现3个a => /a{3}/
-正则表达式中出现3个ab=>/(ab){3}/
-正则表达式中出现1-3次数量的b,但一定要同时左边有a,右边有b=>/ab{1,3}c/
-正则表达式中b至少出现一次,/b+/
-正则表达式中b出现任意次,也就是0次或多次,/b*/
-正则表达式b中出现0次或1次,/b?/
-正则表达式以a开头的字符串,/^a/
-正则表达式以a结尾,/a$/
11.3 字符串和正则相关的方法
- split()方法
作用:用来拆字符串,这个方法即使不指定全局,也会自动指定全局
举例:
var str="12a3,45s6,78s4,454s5"
//一般方法即不用正则的split()方法
var result=str.split(",");//按逗号拆
//按正则表达式拆
//此处的正则表达式是按任意字母拆
var result=str.split(/[A-z]/);
- search()方法
类似Indexof(),也是返回下标,也就是索引,但是它可以接受正则表达式作为条件搜索
可以搜索字符串中是否含有指定内容
如果没有该内容,则返回-1
search()不能设置全局匹配,只能查找第一个,就算设置了全局,也是无效的
举例:
var str="hello abc hello abc";
//用字符串搜索
var result=str.search("abc");//=>输出为:6,也就是说出现在索引为6的地方
//用正则表达式搜索
//搜索字符串中是否含有abc或aec或afc
var result=str.search(/a[bef]c/);
- match()
-可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
-默认情况下我们的match只能找到第一个符合要求的内容,找到以后就会停止检索,我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
-match()会将匹配到的所有内容封装到一个数组中返回,即使只查询到一个结果
//默认的情况下
var t="8aa5s5";
var result=t.match(/[A-z]/);//=>输出a
//设置正则表达式为全局匹配模式下
var t="8aa5s5";
var result=t.match(/[A-z]/g);//=>输出一个数组["a", "a", "s"];
- replace()
-可以将字符串中指定内容替换为新的内容
-参数:
1.被替换的内容,可以接受一个正则表达式作为参数,也可以是一个字符串
2.新的内容
-默认之会匹配第一个,需要在正则表达式中使用全局表达式
var str="ahjhgjh464a64a454";
var result=str.replace(/[A-z]/g,"帅");
console.log(result);//输出=>帅帅帅帅帅帅帅464帅64帅454,字符串类型
11.4 常用的正则表达式的一些例子
//创建一个正则表达式,用来检查是否是一个合法的手机号
//手机号规则:11位,第一位以1开头,第二位3-9任意数字,三位以后任意数字9个
var reg=/^1[3-9][0-9]{9}$/;
//去除字符串中前后的空格,用空串替换
//去除字符串中开头的空格:
var str=" hjj jk jk ";
str=str.replace(/^\s*/,"");
//去除字符串中结尾的空格
str=str.replace(/\s*$/,"");
//去除字符串中开头结尾的空格,开头结尾空格一起去掉
str=str.replace(/^\s*|\s*$/g,"");
//创建一个邮箱的正则表达式
//邮箱举例:hello.nihao@abc.com.cn
//邮箱拆分来方便写正则表达式:hello .nihao @ abc .com .cn
//邮箱规则:开头:任意字母数字下划线;其次,.任意字母数字下划线(可有可无);其次 @;其次,任意字母数字;其次 .任意字母(2-5)位;其次.任意字母(2-5)位(可有可无)
//尝试写正则表达式
//\w{3,} (\.\w+)* @ [A-z][0-9]+ (\.[A-z]{2,5}){1,2}
var reg=/^\w{3,}(\.\w+)*@[A-z][0-9]+(\.[A-z]{2,5}){1,2}$/;
13. 定时器
setInterval
:
-定时调用
-可以将一个函数,每隔一段时间执行一次
-参数:
- 回调函数,该函数会每隔一段时间执行一次
- 每次调用间隔的时间,单位是毫秒
-返回值:
- 返回一个number类型的数据
- 这个数字用来作为定时器的唯一标识
举例:将一个p
标签里显示的文字每隔一段时间自己增加一次
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p></p>
<script>
var t=document.getElementsByTagName('p')[0];
var number=0;
setInterval(function(){t.innerText=number++;},1000);
</script>
</body>
</html>
clearInterval()
:可以用来关闭一个定时器,方法中需要一个定时器的标识作为参数
比如:clearInterval(timer)
,里面的timer是setInterval
的返回值
aetTimeout()
:延时调用,延时调用一个函数不马上执行,而是隔一段时间执行,而且只会执行一次,也有返回体
-参数:
- 函数体
- 延时时间,单位毫秒
clearTimeout()
:关闭一个调用延时,参数是延时调用的返回值