1、ECMAScript和JavaScript的关系
前者是后者的规格,后者是前者的一种实现。
2、JS语句、标识符
- 每一行就是一个语句。
var num=10;
- 标识符是由:字母、美元符号($)、下划线(_)和数字组成,其中数字不能开头。
(注:中文是合法的标识符,可以用作变量名,但不推荐)
- JavaScript保留关键字
arguments、break、case、catch、class、const、continue、debugger、default、delete、 do、else、enum、eval、export、 extends、false、 finally、for、 function、ifimplements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、 while、with、 yield...
3、变量
- var num = 10;中num为变量。
- num=20;即对变量的重新赋值。
- console.log();为打印变量的语句。
- 变量提升:JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成地结果,就是所有变量地声明语句,都会被提升到代码地头部,这就叫变量提升。
console.log(num);
var num=10; //结果是什么呢?
在程序中程序的实际执行如下:
var num;
console.log(num);
num=10;
因此程序运行的结果是 undefined
4、JavaScript引入到文件
- 嵌入到HTML文件中
<body>
<script>
var age =20;
console.log(age);
</script>
</body>
- 引入本地独立JS文件
<body>
<script src="../JavaScript/hello.js"></script>
</body>
- 引入网络来源文件
<body>
<script src="https://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"> </script>
</body>
5、JavaScript注释与常见输出方式
- 注释(注释的快捷键:ctrl+/ )
<script>
// 这是单行注释
/*
这是多行注释
*/
</script>
- JavaScript输出方式
在浏览器中弹出一个对话框,然后把要输出的内容展示处理,alert都是把要输出的内容首先转换为字符串然后再输出的。
alert()是弹出框;document.write()是输出到页面;console.log()在控制台输出内容。
<script>
var age=20;
alert("我是弹出框");
document.write("我是输出到页面");
console.log(age);//在控制台输出内容
</script>
6、数据类型
数据类型有6种,包括数值number、字符串string、布尔值boolean、对象object、undefined、null。
ES6又增加了2种,包括Symbol类型和BigInt类型。
- 原始类型(基础类型):数值、字符串、布尔值
//数值
var age = 20;
//字符串类型:被双引号或单引号包裹的值就是字符串类型
var name = "张三";
var name2 = '李四';
//布尔类型:计算机是由0和1组成,0代表false,1代表true
var learn = true;
var learn2 = false;
- 合成类型(复合类型):包含数值、字符串、布尔值三种
- 对象:因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器
// 引用数据类型,合成数据类型,复合数据类型:object(对象)
var user = {
age:18,
name:"张三",
IsMarry:false,
}
- undefined和null,一般将它们看成两个特殊值。(null一般代表对象为"没有",undefined一般代表数值为“没有”)
7、typeof运算符
typeof用来判断一个值到底是什么类型,一般用来判断数值、字符串、布尔值,判断其他类型其他不太准确。
<script>
var age=20;
var name='zhangsan';
var flag=true;
var user={};
// typeof:判断数据类型(判断基本数据类型使用)
console.log(typeof age);//number
console.log(typeof name);//string
console.log(typeof flag);//boolean
console.log(typeof user);//object(可以返回object的有很多情况)
console.log(typeof []);//object
console.log(typeof null);//object
console.log(typeof undefined)//undefined
</script>
8、运算符:算术运算符
算术运算符包括加法运算符、减法运算符、乘法运算符、除法运算符、余数运算符、自增运算符、自减运算符。
- 加+、减-、乘×、除/
- 取余%
- 自增++、自减--
- 注意:自增自减运算符有两种形式,例如num++,++num;放在变量之后会先返回变量操作前的值,再进行自增/自减操作;放在变量之前会先进行自增/自减操作,再返回变量操作后的值。
<script>
var num1 = 100;
var num2 = 10;
//加减乘除
console.log(num1+num2);//110
console.log(num1-num2);//90
console.log(num1*num2);//1000
console.log(num1/num2);//10
//取余
console.log(num1%num2);//0
//自增或者自减运算符相当于 当前值+1或者-1
var num3=20;
console.log(++num3);//21
console.log(--num3);//20
//自增和自减有两种写法 ++num num++
//++在前先自增再运算,++在后先运算再自增
var num4=10;
var num5=10;
console.log(++num4);//11
console.log(num5++);//10
</script>
9、运算符:赋值运算符
- 赋值运算符用于给变量赋值
- 最常见的赋值运算符是等号(=)
<script>
//将100赋值给num1
var num1 = 100;
//将num1的值赋值给num2
var num2 = num1;
</script>
- 赋值运算符还可以与其他运算符结合,形成变体。
运算符 | 表达式 |
= | 赋值运算符 |
+= | x+=y等同于x=x+y |
-= | x-=y等同于x=x-y |
*= | x*=y等同于x=x*y |
/= | x/=y等同于x=x/y |
%= | x%=y等同于x=x%y |
10、运算符:比较运算符
- 比较运算符用于比较两个值的大小,返回一个布尔值,表示是否满足指定的条件。
- 双等比较值,三等比较值和类型。
比较运算符 | 描述 |
< | 小于运算符 |
> | 大于运算符 |
<= | 小于或等于运算符 |
>= | 大于或等于运算符 |
== | 相等运算符 |
=== | 严格相等运算符 |
!= | 不相等运算符 |
!== | 严格不相等运算符 |
<script>
var num1=10;
var num2="10";
console.log(num1==num2);//true
// === 严格比较:数值本身是否相同,类型本身是否相同
console.log(num1===num2);//false
console.log(num1!=num2);//false
console.log(num1!==num2);//true
</script>
11、运算符:布尔运算符
- 取反运算符(!)
①布尔值取反
!true //false
!false //true
②非布尔值取反
以下六个值取反后都为true,其他值都为false。
undefined
null
false
0
NaN
空字符串('')
- 且运算符(&&)
多个条件都要满足,否则返回false,任何一个条件不满足都返回false。
- 或运算符(||)
满足一个条件即为true,都不满足才返回false。
12、条件语句
- if语句
if(布尔值){
语句;
}
注意:赋值表达式不具有比较作用。
- if-else语句
if(布尔值){
//满足条件时,执行的语句
}else{
//不满足条件时,执行的语句
}
- else-if语句
if(布尔值){
语句;
}else if(布尔值){
语句;
}else{
语句;
}
- if-else嵌套
if(布尔值){
语句;
if(布尔值){
语句;
}else{
语句;
}
}else{
语句;
}
- switch语句
switch(fruit){
case "banana":
//...
break;
case "apple":
//...
break;
default:
//...
}
- 三目运算符
(条件)?表达式1:表达式2
为真则执行表达式1,为假则执行表达式2。
13、循环语句
- for循环
for(初始化表达式;条件;迭代因子){
语句;
}
- while循环
while(条件){
语句;
}
- break语句和continue语句
break语句用于跳出代码块或者循环。
continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。
14、字符串
- 定义:
- 字符串结束零个或多个排在一起的字符,放在单引号或双引号之中。
- 单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号。(注意:不能单引号嵌套单引号,双引号嵌套双引号)
- 如果要做单引号字符串的内部使用单引号,就必须在内部的单引号前面加上反斜杠,用来转义,双引号也是如此。
- 字符串默认只能一行显示,如果需要换行,需要转义 " \ "
- 字符串长度:length属性
- 字符串返回指定字符charAt()
- charAt方法返回指定位置的字符,参数是从0开始编号的
- 如果参数为负数,或者大于等于字符串长度,charAt返回空字符串
- 字符串连接concat()
- concat方法用于连接两个字符串,返回一个新字符串,不改变原字符串
- 该方法可以接受多个参数
- 如果参数不是字符串,concat方法会将其先转为字符串,然后再连接
- 字符串连接还可以使用 “ + ” 连接
- concat和“+”是有区别的:concat不管什么类型直接做字符串相连接,而“+”遇到数字类型会先做运算再连接
- 字符串截取substring()
- substring方法用于从字符串取出子字符串并返回,不改变原字符串。它的第一个参数表示子字符串的开始位置,第二个位置表示结束位置(返回结果不包含该位置)
- 如果省略第二个参数,则表示子字符串一直到原字符串的结束
- 如果第一个参数大于第二个参数,substring方法会自动更换两个参数的位置
- 如果参数是负数,substring方法会自动将负数转为0
- 字符串截取substr()
- substr方法用于从原字符串取出子字符串并返回,不改变原字符串,跟substring方法作用相同
- substr方法的第一个参数是子字符串的开始位置(从0开始),第二个参数是子字符串的长度
- 如果省略第二个参数,则表示子字符串一直到原字符串的结束
- 如果第一个参数是负数,表示倒数计算的字符位置。如果第二个参数是负数,会被自动转为0,因此会返回空字符串
- 字符串搜索indexOf()
- indexOf方法用于确定一个字符串在另一个字符串中第一次出现的位置,返回结果是匹配开始的位置。如果返回-1,就表示不匹配。
- indexOf方法还可以接受第二个参数,表示从该位置开始向后匹配
- 去除字符串两端空格trim()
- trim方法用于去除字符串两端的空格,返回一个新字符串,不改变原字符串
- 该方法去除的不仅是空格,还包括制表符(\t、\v)、换行符(\n)和回车符(\r)
- ES6扩展方法,trimEnd()和trimStart()方法
- 字符串分割split()
- split方法按照给定规则分割字符串,返回一个由分割出来的子字符串组成的数组
- 如果分割规则为空字符串,则返回数组的成员是原字符串的每一个字符
- 如果省略参数,则返回数组的唯一成员就是原字符串
- split方法还可以接受第二个参数,限定返回数组的最大成员数
15、数组
1、数组赋值
- ①定义时赋值:var arr = [ 100, [1,2,3], false ];
- ②先定义后赋值:var arr = []; var[0] = 'sxt' ;
- 任何类型的数据都可以放入数组。
- 如果数组的元素还是数组,就形成了多维数组。
- length属性返回数组的成员数量。
- 数组越界会返回undefined
2、数组的遍历
<script>
var arr = ['txt','jiji','scy','lklk'];
// for循环遍历
for(var i=0;i<arr.length;i++){
console.log(arr[i]);
}
// while循环遍历
var i=0;
while(i<arr.length){
console.log(arr[i]);
i++;
}
// for-in遍历
for(var i in arr){
console.log(arr[i]);
}
</script>
3、数组静态方法Array.isArray()
- Array.isArray方法返回一个布尔值,表示参数是否为数组。它可以弥补typeof运算符的不足。
4、数组方法push() / pop()
- push方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
- pop方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组。
5、数组方法shift() /unshift()
- shift()方法用于删除数组的第一个元素,并返回该元素。
- shift方法可以遍历并清空一个数组。
<script>
var list=[100,200,300];
var i;
while(i=list.shift()){
console.log(i);
}
console.log(list);
</script>
- unshift()方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组的长度。
- unshift方法可以接受多个参数,这些参数都会添加到目标数组头部。
6、数组方法join()
- join方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分隔。
- 如果数组成员是undefined或null或空位,会被转成空字符串。
- 数组的join配合字符串的split可以实现数组与字符串的互换。
<script>
var arr=['hello','world'];
var result=arr.join(" ");
console.log(result);
console.log(result.split(" "));
</script>
7、数组方法concat()
- concat方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。
- 除了数组作为参数,concat也接受其他类型的值作为参数,添加到目标数组尾部。
<script>
var arr=['hello','world'];
console.log(arr.concat(10,20,30));//['hello', 'world', 10, 20, 30]
</script>
- 应用场景:上拉加载,合并数据
8、数组方法reverse()
- reverse方法用于颠倒排列数组元素,返回改变后的数组。
- 实现字符串反转。
<script>
var arr='helloworld';
var a1=arr.split("");
console.log(a1);
var a2=a1.reverse();
console.log(a2.join(""));
</script>
9、数值方法indexOf()
- indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。
- indexOf方法还可以接受第二个参数,表示搜索的开始位置。
16、函数
1、函数的声明
function命令:function命令声明的代码区块,就是一个函数。function命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函数体放在大括号里面。
function print(s){
console.log(s);
}
2、函数名的提升
JavaScript引擎将函数名视为变量名,所以采用function命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。因此可以先调用再声明。
add();
function add(x,y){
console.log(x+y);
}
3、函数参数
函数运行的时候,有时需要提供外部数据,不同的外部数据会得到不同的结果,这种外部数据就叫参数。
4、函数返回值return
JavaScript函数提供两个接口实现与外界的交互,其中参数作为入口,接受外界信息;返回值作为出口,把运算结果反馈给外界。
函数体里return语句后的代码不执行。
17、对象
1、对象概述
- 对象(object)是一组“键值对”的集合,是一种无序的复合数据集合。
- 对象的每一个键名又称为“属性”,它的“键值”可以是任何数据类型。如果一个属性的值为函数,通常把这个属性成为“方法”。
- 对象读取方式:对象名.属性
- 如果属性的值还是一个对象,就形成了链式引用。
<script>
// 创建一个对象user
var user={
name:'txtkiki',
age:1,
jobs:['doctor','teacher'],
flag:true,
getName:function(){
console.log('scc');
},
container:{
frontEnd:'web前端',
backEnd:['java','c']
}
}
// 对象的读取方式:对象名.属性
console.log(user.name);
console.log(user.jobs);
for(var i=0;i<user.jobs.length;i++){
console.log(user.jobs[i]);
}
user.getName();
// 链式调用
console.log(user.container.frontEnd);
</script>
2、Math对象
提供各种属性功能。
- Math.abs()方法返回参数值的绝对值
- Math.max()方法和Math.min()方法返回最大值和最小值
- Math.floor()方法返回小于参数值的最大整数(向下取整)
- Math.ceil()方法返回大于参数值的最小整数(向上取整)
- Math.random()返回0到1之间的一个伪随机数,可能等于0,但是一定小于1
- 任意范围的随机数生成函数如下:
function getRandomArbitrary(min,max){
return Math.random()*(max-min)+min;
}
console.log(getRandomArbitrary(5,10));
3、Date对象
Date以1970年1月1日00:00:00作为时间的零点。(单位为毫秒)
- 时间戳Date.now()
- 实例方法get类(new Date().方法名调用)
- getTime():返回实例距离1970年1月1日00:00:00的毫秒数
- getDate():返回实例对象对应每个月的几号(从1开始)
- getDay():返回星期几,星期日为0,星期一为1,以此类推
- getYear():返回距离1900的年数
- getFullYear():返回四位的年份
- getMonth():返回月份(0表示1月,11表示12月)
- getHours():返回小时(0-23)
- getMilliseconds():返回毫秒(0-999)
- getMinutes():返回分钟(0-59)
- getSeconds():返回秒(0-59)
- 实例:编写函数获得本年度剩余天数
function leftDays(){
var today = new Date();
var endYear = new Date(today.getFullYear(),11,31,23,59,59,999);// 使用11表示12月
var maPerDay=24*60*60*1000;// 一天的毫秒数
var result=(endYear.getTime()-today.getTime())/maPerDay;// 计算剩余天数
console.log(Math.floor(result));
}
leftDays();
18、DOM
DOM是JavaScript操作网页的接口,全称为“文档对象模型”(Document Object Model)。它的作用是将网页转为一个JavaScript对象,从而可以用脚本进行各种操作(比如对元素增删内容)
浏览器会根据DOM模型,将结构化文档HTML解析成一系列的结点,再由这些节点组成一个树状结构(DOM Tree)。所以的节点和最终的树状结构,都有规范的对外接口。
DOM只是一个接口规范,可以用各种语言实现。所以严格地说,DOM不是JavaScript语法的一部分,但是DOM操作是JavaScript最常见的任务,离开了DOM,JavaScript就无法控制页面。另一方面,JavaScript也是最常用于DOM操作的语言。
1、节点
DOM的最小组成单位叫做节点(node)。文档的树形结构(DOM树),就是由各种不同类型的节点组成,每个节点可以看作是文档树的一片叶子。
2、节点的类型有七种
Document:整个文档树的顶层节点
DocumentType:doctype标签
Element:网页的各种HTML标签
Attribute:网页元素的属性(比如class=“right”)
Text:标签之间或标签包含的文本
Comment:注释
DocumentFragment:文档的片段
3、节点数
浏览器原生提供document节点,代表整个文档
document // 整个文档树
除了根节点,其他节点都有三种层级关系:父节点关系、子节点关系、同级节点关系
4、Node.nodeType属性
不同节点的nodeType属性值和对应常量如下:
文档节点(document):9,对应常量Node.DOCUMENT_NODE
元素节点(element):1,对应常量Node.ELEMENT_NODE
属性节点(attr):2,对应常量Node.ATTRIBUTE_NODE
文本节点(text):3,对应常量Node.TEXT_NODE
文档片段节点(DocumentFragment):11,对应常量Node.DOCUMENT_FRAGMENT_NODE
19、document对象方法:获取元素
1、document.getElementsByTagName()
document.getElementsByTagName方法搜索HTML标签名,返回符合条件的元素。它的返回值是一个类似数组对象(HTMLCollection实例),可以实时反映HTML文档的变化。如果没有任何匹配的元素,就返回一个空集。
var paras = document.getElementsByTagName('p'); //获取p标签
<div>hello1</div>
<div>hello2</div>
<script>
var div1=document.getElementsByTagName("div")[0];
div1.innerHTML = "Hello World";
</script>
如果传入*,就返回文档中所有HTML元素
var allElements = document.getElementsByTagName('*');
2、document.getElementsByClassName()
document.getElementsByClassName方法返回一个类似数组的对象(HTMLCollection实例),包含了所有class名字符合指定条件的元素,元素的变化实时反映在返回结果中。
由于class是保留字,所以JavaScript一律使用className表示CSS的class参数。参数可以是多个class,它们之间使用空格分隔。
var elements = document.getElementsByClassName('foo bar');
<p class="text">Hello</p>
<script>
var text=document.getElementsByClassName("text")[0];
text.innerHTML = "Hello!";
</script>
3、document.getElementsByName()
document.getElementsByName方法用于选择拥有name属性的HTML元素(比如<form>、<radio>、<img>等),返回一个类似数组的对象(NodeList实例),因为name属性相同的元素可能不止一个。
<form name="sss"></form>
<script>
var sss=document.getElementsByName('sss');
console.log(sss);
</script>
4、document.getElementById()
document.getElementById方法返回匹配指定id属性的元素节点。如果没有发现匹配的节点,则返回null。注意,该方法的参数是参数大小写敏感的。比如,如果某个节点的id属性是main,那么document.getElementById('Main')将返回null。
<div id="root">哈哈哈</div>
<script>
var root=document.getElementById('root');
root.innerHTML="呵呵呵";
</script>
5、document.querySelector()
document.querySelector方法接受一个CSS选择器作为参数,返回匹配该选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回null。
6、document.querySelectorAll()
document.querySelectorAll方法与document.querySelector方法用法类似,区别是返回一个NodeList对象,包含所有匹配给定选择器的节点。
<div class="nav">nav1</div>
<div class="nav">nav2</div>
<script>
var nav = document.querySelector(".nav");
console.log(nav);
var navs = document.querySelectorAll(".nav");
console.log(navs);
</script>
20、document对象方法:创建元素
1、document.creatElement()
document.creatElement方法用来生成元素节点,并返回该节点。
var newp = document.createElement('p');
console.log(newp);
2、document.creatTextNode()
document.creatTextNode方法用来生成文本节点(Text实例),并返回该节点。它的参数是文本节点的内容。
<script>
var newp = document.createElement('p');
var text = document.createTextNode('我是文本');
// appendChild:将内容或者子元素放到容器中
newp.appendChild(text);
console.log(newp);
</script>
3、document.creatAttribute()
document.creatAttribute方法生成一个新的属性节点(Attr实例),并返回它。
<div id="container"></div>
<script>
var newp = document.createElement('p');
var text = document.createTextNode('我是文本');
var id = document.createAttribute('id');
id.value='root';
// appendChild:将内容或者子元素放到容器中
newp.appendChild(text);
// setAttributeNode:将标签放到容器中
newp.setAttributeNode(id);
console.log(newp);
var container = document.getElementById('container');
container.appendChild(newp);
console.log(container);
</script>
21、Element对象
1、属性
Element对象对应网页的HTML元素。每一个HTML元素,在DOM树上都会转化成一个Element节点对象。
1、Element.id
Element.id属性返回指定元素的id属性,该属性可读写。
<div class="box" id="root">Hello</div>
<script>
var root = document.getElementById("root");
root.id = "roots";
console.log(root.id);
</script>
2、Element.className
className属性用来读写当前元素节点的class属性。它的值是一个字符串,每个class之间用空格分割。
<style>
.box{
width: 200px;
height: 200px;
}
.box1{
background-color: red;
}
</style>
<body>
<div class="box" id="root">Hello</div>
<script>
var root = document.getElementById("root");
root.className="box box1";//box
console.log(root.className);
</script>
</body>
3、Element.classList
classList对象有下列方法:
- add():增加一个class
- remove():移除一个class
- contains():检查当前元素是否包含某个class
- toggle():将某个class移入或移出当前元素
<script>
var root = document.getElementById("root");
root.className="box box1";//box
console.log(root.classList.add("mybox"));
root.classList.remove('box');
if(root.classList.contains('box1')){
console.log("yes");
}else{
console.log("NO");
}
</script>
4、Element.innerHTML
Element.innerHTML属性返回一个字符串,等同于该元素包含的所有HTML代码。该属性可读写,常用来设置某个节点的内容。它能改写所有元素节点的内容,包括<HTML>和<body>元素。
console.log(root.innerHTML);
root.innerHTML="大家好呀!";
innerText和innerHTML的作用类似。
innerHTML和innerText的区别:innerHTML可以识别标签,innerText会把标签识别成一个字符串。
2、获取元素位置
属性 | 描述 |
clientHeight | 获取元素高度,包括padding部分,但是不包括border、margin |
clientWidth | 获取元素宽度,包括padding部分,但是不包括border、margin |
scrollHeight | 元素总高度,它包括padding,但是不包括border、margin包括溢出的不可见内容 |
scrollWidth | 元素总宽度,它包括padding,但是不包括border、margin包括溢出的不可见内容 |
scrollLeft | 元素的水平滚动条向右滚动的像素数量 |
scrollTop | 元素的垂直滚动条向下滚动的像素数量 |
offsetHeight | 元素的CSS垂直高度(单位元素),包括元素本身的高度、padding和border |
offsetWidth | 元素的CSS水平宽度(单位像素),包括元素本身的高度、padding和border |
offsetLeft | 到定位父级左边界的间距 |
offsetTop | 到定位父级上边界的间距 |
// 获取视口高度(屏幕高度)
console.log(document.documentElement.clientHeight);
// 获取页面高度
console.log(docum ent.body.clientHeight);
<style>
*{
margin: 0;
padding: 0;
}
.box{
width: 200px;
height: 200px;
border: 5px solid red;
padding: 10px;
margin :20px;
background: green;
}
h3{
height: 500px;
}
.box2{
width: 200px;
height: 200px;
background-color: red;
margin: 100px;
}
</style>
<body>
<div class="box" id="box"></div>
<h3>biaoti1</h3>
<h3>biaoti2</h3>
<h3>biaoti3</h3>
<div class="box2" id="box2"></div>
<script>
var box=document.getElementById("box");
console.log(box.clientHeight);
console.log(box.clientWidth);
// 获取视口高度(屏幕高度)
console.log(document.documentElement.clientHeight);
// 获取页面高度
console.log(document.body.clientHeight);
console.log("------------------");
console.log(box.scrollHeight);
console.log(box.scrollWidth);
// 获取视口高度(屏幕高度)
console.log(document.documentElement.scrollHeight);
// 获取页面高度
console.log(document.body.scrollWidth);
// 获取滚动高度
console.log(document.documentElement.scrollTop);
console.log("-------------------");
console.log(box.offsetWidth);
console.log(box.offsetHeight);
console.log("-------------------");
var box2=document.getElementById("box2");
console.log(box2.offsetLeft);
console.log(box2.offsetTop);
</script>
</body>
22、CSS操作
1、HTML元素的style属性
操作CSS样式最简单的方法,就是使用网页元素节点的setAttribute方法直接操作网页元素的style属性。
<div class="box" id="box"></div>
<script>
var box=document.getElementById("box");
box.setAttribute('style','width:200px;height:200px;background:red;');
</script>
2、元素节点的style属性
<div class="box" id="box"></div>
<script>
var box=document.getElementById("box");
box.style.width="300px";
box.style.height="300px";
box.style.backgroundColor="red";
</script>
3、cssText属性
<div class="box" id="box"></div>
<script>
var box=document.getElementById("box");
box.style.cssText="width:200px;height:200px;background:red;";
</script>
23、事件处理程序
- HTML事件处理(缺点:HTML和JS没有分开)
<body>
<button onclick="clickHandle()">按钮</button>
<script>
function clickHandle(){
console.log("点击了按钮");
}
</script>
</body>
- DOM0级事件处理(优点:HTML和JS是分离的,缺点:不能同时添加多个事件)
<body>
<button id="btn">按钮</button>
<script>
var btn=document.getElementById("btn");
btn.onclick=function(){
console.log("点击了");
}
</script>
</body>
- DOM2级事件处理(优点:事件不会被覆盖,缺点:写起来麻烦)
<button id="btn">按钮</button>
<script>
var btn=document.getElementById("btn");
btn.addEventListener("click",function(){
console.log("点击了");
})
</script>
24、事件类型
1、鼠标事件
- click:按下鼠标时触发
- dblclick:在同一个元素上双击鼠标时触发
- mousedown:按下鼠标键时触发
- mouseup:释放按下的鼠标键时触发
- mousemove:当鼠标在节点内部移动时触发。当鼠标持续移动时,该事件会连触发。
- mouseenter:鼠标进入一个节点时触发,进入子节点不会触发这个事件
- mouseleave:鼠标离开一个节点时触发,离开父节点不会触发这个事件
- mouseover:鼠标进入一个节点时触发,进入子节点会再一次触发这个事件
- mouseout:鼠标离开一个节点时触发,离开父节点也会触发这个事件
- wheel:滚动鼠标的滚轮时触发
<style>
#btn5{
width: 50px;
height: 50px;
background-color: red;
}
#btn6{
width: 50px;
height: 50px;
background-color: rgb(0, 255, 60);
}
#btn7{
width: 50px;
height: 50px;
background-color: rgb(0, 213, 255);
}
</style>
</head>
<body>
<button id="btn1">单击</button>
<button id="btn2">双击</button>
<button id="btn3">鼠标按下</button>
<button id="btn4">鼠标抬起</button>
<div id="btn5"></div>
<div id="btn6"></div>
<div id="btn7"></div>
<script>
var btn1=document.getElementById("btn1");
btn1.onclick=function(){
console.log("单击事件");
}
var btn2=document.getElementById("btn2");
btn2.ondblclick=function(){
console.log("双击事件");
}
var btn3=document.getElementById("btn3");
btn3.onmousedown=function(){
console.log("鼠标按下");
}
var btn4=document.getElementById("btn4");
btn4.onmouseup=function(){
console.log("鼠标抬起");
}
var btn5=document.getElementById("btn5");
btn5.onmousemove=function(){
console.log("鼠标移动");
}
var btn6=document.getElementById("btn6");
btn6.onmouseenter=function(){
console.log("鼠标进入");
}
var btn7=document.getElementById("btn7");
btn7.onmouseleave=function(){
console.log("鼠标离开");
}
</script>
</body>
2、Event事件对象
事件发生以后,会产生一个事件对象,作为参数传给监听函数。
<button id="btn">按钮</button>
<script>
var btn=document.getElementById("btn");
// Event事件对象,其实就是参数
btn.onclick=function(event){
console.log(event);
}
</script>
- Event.target属性返回事件当前所在的节点
<button id="btn">按钮</button>
<script>
var btn=document.getElementById("btn");
// Event事件对象,其实就是参数
btn.onclick=function(event){
console.log(event.target);
// 点击后获得<button id="btn">按钮</button>
}
</script>
- Event.type属性返回一个字符串,表示事件类型。事件的类型是在生成事件的时候。该属性只读。
<button id="btn">按钮</button>
<script>
var btn=document.getElementById("btn");
// Event事件对象,其实就是参数
btn.onclick=function(event){
console.log(event.type);//点击后返回click
}
</script>
- Event.preventDefault()方法
Event.preventDefault方法取消浏览器对当前事件的默认行为。比如点击链接后,浏览器默认会跳转到另一个页面,使用这个方法以后,就不会跳转了。
<a href="https://baidu.com" id="bai">baidu</a>
<script>
var bai=document.getElementById("bai");
bai.onclick=function(event){
event.preventDefault();//阻止默认事件
console.log("点击链接");
}
</script>
- Event.stopPropagation()方法
Event.stopPropagation方法阻止事件在DOM中继续传播,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上其他的事件监听函数。(阻止事件冒泡)
<style>
.root{
width: 200px;
height: 200px;
background-color: rgb(197, 202, 207);
}
.box{
width: 100px;
height: 100px;
background-color: rgb(240, 33, 33);
}
</style>
</head>
<body>
<div class="root" id="root">
<div class="box" id="box"></div>
</div>
<script>
var root=document.getElementById("root");
var box=document.getElementById("box");
root.onclick=function(e){
console.log("root");
}
box.onclick=function(e){
e.stopPropagation();
console.log("box");
}
</script>
</body>
3、键盘事件
键盘事件由用户击打键盘触发,主要有keydown、keypress、keyup三个事件。
- keydown:按下键盘时触发。
- keypress:按下有值得键时触发,即按下Ctril、Alt、Shift、Meta这样无值得键,这个事件不会触发。对于有值得键,按下时先触发keydown事件,再触发这个事件。
- keyup:松开键盘时触发该事件。
- event对象:keyCode唯一标识
<input type="text" id="username">
<input type="text" id="password">
<script>
var username=document.getElementById("username");
username.onkeydown=function(){
console.log("按下键盘");
}
username.onkeyup=function(e){
console.log(e.target.value);//value属性是获取输入的数据
}
// tril、Alt、Shift、Meta
username.onkeypress=function(){
console.log("keypress");
}
var password=document.getElementById("password");
password.onkeyup=function(e){
// keyCode代表每个按键的唯一标识
console.log(e.keyCode);
if(e.keyCode==13){
console.log("回车");
}
}
</script>
4、表单事件
表单事件是在使用表单元素及输入框元素可以监听的一系列事件。
- input事件
input事件当<input>、<select>、<textarea>的值发生变化时触发。对于复选框(<input type=checkbox>)或单选框(<input type=radio>),用户改变选项时,也会触发这个事件。
- select事件
select事件当在<input>、<textarea>里面选中文本时触发。
- Change事件
Change事件当<input>、<select>、<textarea>的值发生变化时触发。它与input事件的最大不同,就是不会连续触发,只有当全部修改完成才会触发。
- reset事件、submit事件
这两个事件发生在表单的<form>上,而不是发生在表单的成员上。
reset事件当表单重置(所有表单成员变回默认值)时触发。
submit事件当表单数据向服务器提交时触发。
<body>
<input type="text" id="username">
<input type="text" id="password">
<!-- action存放服务器地址 -->
<form action="" id="Myform" onsubmit="submitHandle">
<input type="text">
<button id="resetBtn">重置</button>
</form>
<script>
var username=document.getElementById("username");
username.oninput=function(e){
console.log(e.target.value);
}
username.onselect=function(){
console.log("选中内容");
}
var password=document.getElementById("password");
password.onchange=function(e){
console.log(e.target.value);
}
var resetBtn=document.getElementById("resetBtn");
var Myform=document.getElementById("Myform");
resetBtn.onclick=function(){
Myform.reset();//触发在表单上:清空表单
}
function submitHandle(){
console.log("想做的事情");
}
</script>
</body>
5、事件代理(事件委托)
由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理。
<body>
<!-- 点击所有li标签生效 -->
<ul id="list">
<li>列表1</li>
<li>列表2</li>
<p>哈哈哈</p>
</ul>
<script>
var list=document.getElementById("list");
list.addEventListener("click",function(e){
if(e.target.tagName.toLowerCase() =="li"){
console.log("点击了LI标签");
console.log(e.target.innerHTML);
}
});
</script>
</body>
25、定时器
JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数完成。它们像任务队列添加定时任务。
1、setTimeout()
- setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。
- setTimeout函数接受两个参数,第一个参数func|code是将要推迟执行的函数名或一段代码,第二个参数delay是推迟执行的毫秒数。
<script>
setTimeout(function(){
console.log("延迟3秒执行");
},3000);
</script>
- 注意:如果回调函数是对象的方法,那么setTimeout使得方法内部的this关键字指向全局环境,而不是定义时所在的那个对象。
<script>
var name='sss';
var user = {
name:"xiaoming",
getName:function(){
// this永远指向当前调用者
setTimeout(function(){
console.log(this.name);
},1000)
},
}
user.getName();
</script>
- 解决方案:
<script>
var name='sss';
var user = {
name:"xiaoming",
getName:function(){
// this永远指向当前调用者
var that=this;
setTimeout(function(){
console.log(that.name);
},1000)
},
}
user.getName();
</script>
- 取消定时器的执行clearTimeout()
<script>
var timer=setTimeout(function(){
console.log("延迟1s");
},1000);
clearTimeout(timer);
</script>
2、setInterval()
- setInterval函数的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。
<script>
var i=0;
setInterval(function(){
i++;
console.log(i);
},1000);
</script>
- 实现动画效果:逐渐透明
<style>
#someDiv{
width: 100px;
height: 100px;
background: red;
opacity: 1;
}
</style>
<body>
<div id="someDiv"></div>
<script>
var div=document.getElementById("someDiv");
// 透明度:opacity:取值范围0-1
var opacity=1;
var fade=setInterval(function(){
if(opacity>0){
opacity-=0.05;
div.style.opacity=opacity;
}else{
clearInterval(fade);
}
},100);
</script>
</body>
- 取消定时器clearInterval()
26、防抖debounce
防抖严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死。
- 滚动监听的例子
<style>
h3{
height: 400px;
}
</style>
<body>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<script>
// 滚动事件
window.onscroll=scrollHandle;
function scrollHandle(){
// 打印滚动高度
var scrollTop=document.documentElement.scrollTop;
console.log(scrollTop);
}
</script>
</body>
但是在上述场景中执行频率太高了,因此我们要优化。
第一种思路:在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms,然后
①如果在200ms内没有再次触发滚动事件,那么就执行函数。
②如果在200ms内再次触发滚动事件,那么当前的计时取消,重新开始计时。
效果:如果短时间内大量触发同一事件,只会执行函数一次。
- 实现:实现的关键在于setTimeout这个函数,由于还需要一个变量来保存计时,考虑维护全局纯净,可以借助闭包来实现。
<style>
h3{
height: 400px;
}
</style>
<body>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<script>
function debounce(fn,delay){
var timer=null;
// 闭包
return function(){
if(timer){
clearTimeout(timer);
}
timer=setTimeout(fn,delay);
}
}
// 滚动事件
window.onscroll=debounce(scrollHandle,200);
function scrollHandle(){
// 打印滚动高度
var scrollTop=document.documentElement.scrollTop;
console.log(scrollTop);
}
</script>
</body>
到这里,防抖已经实现。
- 防抖定义:对于短时间内连续触发的事件(上面的滚动事件),防抖的含义就是让某个时间期限(如上面的1000ms)内,事件处理函数只执行一次。
27、节流throttle
节流严格算起来应该属于性能优化的知识,但实际上遇到的频率相当高,处理不当或者放任不管就容易引起浏览器卡死。
上面防抖方案来处理问题的结果是:如果在限定时间段内,不断触发滚动事件(比如某个用户按住滚动条不断地拖来拖去),只要不停止触发,理论上就永远不会输出当前距离顶部的距离。
实现:借助setTimeout来做一个简单的实现,加上一个状态位valid来表示当前函数是否处于工作状态。
<style>
h3{
height: 400px;
}
</style>
<body>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<h3>sss</h3>
<script>
function throttle(fn,delay){
var valid = true;
return function(){
if(!valid){
return false;
}
valid = false;
setTimeout(function(){
fn();
valid=true;
},delay);
}
};
// 滚动事件
window.onscroll=throttle(scrollHandle,200);
function scrollHandle(){
// 打印滚动高度
var scrollTop=document.documentElement.scrollTop;
console.log(scrollTop);
}
</script>
</body>
平时开发中遇到的场景:
- 搜索框input事件,例如要支持输入实时搜索可以使用节流方案(间隔一段时间就必须查询相关内容),或者实现输入间隔大于某个值(如500ms),就当做用户输入完成,然后开始搜索,具体使用哪种方案要看业务需求。
- 页面resize事件,常见于需要做页面适配的时候。需要根据最终呈现的页面情况进行dom渲染(这种情形一般是使用防抖,因为只需要判断最后一次的变化情况)