【JavaWeb学习】JavaScript(基础)

对象

对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。

对象的分类

内建对象:由ES标准定义的对象,在任何ES的实现中都可以使用,比如Math、String、Number……
宿主对象:由JS运行环境提供的对象,主要指由浏览器提供的对象,比如BOM、DOM……
自定义对象:由开发人员自己创建的对象

创建一个对象:var obj = new Object();
向对象添加属性:obj.属性名 = 属性值;
读取对象的属性:obj.属性名;
删除对象的属性:delete obj.属性名;
如果读取对象中没有的属性,不会报错,而是会返回undefined。

属性名和属性值
  • 对象的属性名不强制要求遵守标识符的规范,但还是尽量按规范去做。如果要使用特殊的属性名,需要采用另一种方式:对象['属性名'] = 属性值;,读取时也要采用这种方式。
  • 使用[]去操作属性更加灵活,在[]中可以直接传递一个变量,这样,变量值是多少,就会读取那个属性。比如:
var obj = new Object();
obj["123"] = 789;
var n = "123";
console.log(obj[n]);
  • JS的属性值可以是任意的数据类型,可以是基本数据类型,可以是对象,可以是函数。
  • 检查一个对象中是否含有指定的属性:"属性名" in 对象,返回值 truefalse
基本数据类型和引用数据类型

JS中的变量都保存在栈内存中:

  • 基本数据类型的值直接在栈内存中存储,值与值之间独立存在,修改一个变量不会影响其他的变量;
  • 对于引用数据类型,变量保存的是对象的地址,对象保存在堆内存中,每创建一个新的对象,就会在堆内存中开辟出一个新的空间。如果两个变量保存的是同一个地址,那么修改一个变量之后,另一个会跟着改变。
对象字面量 {}
  • 使用对象字面量来创建一个对象:var obj = {};
  • 在创建时指定属性:var obj = { 属性名:属性值, 属性名:属性值, ……};

对象字面量的属性名可以加引号也可以不加,建议不加;如果要使用一些特殊的名字,则必须加引号。
属性名和属性值是一组一组的名值对结构,名和值之间用 : 连接,多个名值对之间用 , 隔开。

函数

函数也是一个对象,可以封装一些功能,在需要时执行这些功能。函数对象也可以有属性。

  • 创建一个函数对象:var func = new Function(); 此时 typeof func 返回值为 function。可以将要封装的代码以字符串的形式传递给构造函数,封装到函数中的代码不会立即执行,而是在函数调用的时候执行。
  • 调用函数:func(); 此时函数中封装的代码会按顺序执行。
  • 函数声明:
function 函数名([形参1, 形参2, ..., 形参N]){
	函数语句...
}
  • 函数表达式:创建一个匿名函数,再将这个匿名函数赋值给一个对象。
var 函数名 = function([形参1, 形参2, ..., 形参N]){
	语句...
}
参数

举例:

function sum(a,b){
	return a + b;
}

\qquad 调用函数时解析器不会检查实参的类型,所以要注意是否会接收到非法的参数,如果有可能,则需要对参数进行类型检查。
\qquad 调用函数时解析器也不会检查实参的数量,多余实参不会被赋值。如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined
实参可以是任意的数据类型。
\qquad 如果return后面不跟任何值或者函数中不写return,都会返回一个undefined。

返回值

\qquad 返回值可以是任意数据类型,当然可以是一个对象,也可以是一个函数。

立即执行函数

\qquad 函数定义完后立即被调用,这种函数往往只会执行一次。举例:

(function(a,b){return a+b;})(123,456);
函数的方法 call() 和 apply()

\qquad 对于一个函数fun(),可以调用上述两个方法:fun.call(); fun.apply();
\qquad 调用时可以指定一个对象作为第一个参数,此时这个对象就会成为函数执行时的 this;后面传入的参数都会作为实参传递给函数fun(); 注意:call() 方法可以将实参在对象之后依次传递,apply()方法需要将实参封装到一个数组中统一传递。

arguments 参数列表

\qquad 在调用函数时,浏览器每次会传递进两个隐含的参数,第一个是函数的上下文对象this,第二个是封装实参的对象arguments。

  • arguments 是一个类数组对象,也可以通过索引来操作数据,可以获取长度;
  • 调用函数时,所有的实参都会在 arguments 中保存,arguments.length就是实参的数量;
  • 即使不定义形参,也可以通过arguments来使用实参;
  • 属性callee对应了当前正在执行的函数对象;

方法

\qquad 如果一个函数作为一个对象的属性保存,那么这个函数称为对象的方法,调用这个函数称为“调用对象的方法”。

枚举对象中的属性

语法:for(var 变量 in 对象){ 操作变量的语句 }
\qquad 对象中有几个属性,循环体就会执行几次;每次执行时,会将对象中的一个属性的名字赋值给变量,可以用obj[变量]取出该属性的值。

var obj = {
			name:"kirlant";
			age:18;
			gender:"female",
			address:"empire"
		};
for(var n in obj){
	console.log(obj[n]);
}

作用域

作用域指定一个变量的作用范围。
变量的声明提前 使用 var 关键字声明的变量会在所有代码执行之前被声明;如果不使用 var 关键字,就不会被声明提前。
函数的声明提前 使用函数声明形式 function 函数名(){} 创建的函数会在所有代码执行之前被创建,所以可以在函数声明之前调用函数;使用函数表达式创建的函数则不会被声明提前。

全局作用域

直接编写在script标签中的代码都在全局作用域中;
全局作用域在页面打开时创建,在页面关闭时销毁;
在全局作用域中,有一个全局对象window,代表浏览器的窗口,由浏览器创建,可以直接使用;
在全局作用域中,创建的变量都会作为window对象的属性保存,创建的函数都会作为window对象的方法保存;
全局作用域中的变量都是全局变量,在页面的任意部分都可以访问到。

函数作用域(局部作用域)

调用函数时创建函数作用域,函数执行完毕后作用域销毁;
每调用一次函数,就会创建一个新的函数作用域,它们之间是互相独立的;
函数作用域中可以访问到全局作用域的变量,而全局作用域中无法访问到函数作用域的变量;
当在函数作用域中操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用,没有就向上一级作用域中寻找;如果直到全局作用域都没有找到,才会报错;
在函数中如果想访问全局变量,可以使用window对象;
在函数作用域中也有声明提前的特性,只是被提前声明,不会一起提前赋值;
函数声明也会在所有代码执行之前被声明;
在函数中,不使用var声明的变量都会成为全局变量;
定义形参就相当于在函数作用域中声明了变量,不传参就相当于变量是undefined。

this

浏览器在调用函数时,每次都会向函数内部传递一个隐含的参数this
this指向一个对象,称为函数执行的上下文对象,根据函数的调用方式不同,this会指向不同的对象

  • 以函数方式调用时,this永远指向window;
  • 以方法方式调用时,this指向调用方法的对象;
  • 以构造函数形式调用时,this指向新建的那个对象;
  • 使用call() 和 apply()调用时,this指向指定的那个对象。

使用工厂方法创建对象

定义一个方法,大批量创建对象:

  1. 创建一个新的对象;
  2. 向对象中添加属性和方法;
  3. 将新的对象返回;
function creatNewObject(name, age, gender, ads){
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.gender = gender;
	obj.address = ads;
	obj.sayName = function(){
		alert(this.name);
	}
	return obj;
}

使用的构造函数都是Object,所以创建的对象都是Object类型,不方便区分对象 ⟶ \longrightarrow 创建一个构造函数,专门用来创建一类对象,函数首字母大写。

构造函数

构造函数要通过 new 关键字调用。执行流程:

  1. 立刻创建一个新的对象;
  2. 将新建的对象设为函数中的 this,在构造函数中用 this 来引用新建的对象;
  3. 逐行执行函数中的代码;
  4. 将新建的对象作为返回值返回;

使用同一个构造函数创建的对象称为一类对象,也将构造函数称为一个类。将通过一个构造函数创建的对象称为该构造函数(或者该类)的实例。

function Person(name, age, gender, ads){
	this.name = name;
	this.age = age;
	this.gender = gender;
	this.address = ads;
	this.sayName = function(){
		alert(this.name);
	}
}
var pers = new Person("kirlant", 16, "female", "empire");
console.log(typeof pers);
console.log(pers);
pers.sayName();

运行结果:

object
Person {
  name: 'kirlant',
  age: 16,
  gender: 'female',
  address: 'empire',
  sayName: [Function (anonymous)]
}
kirlant

检查一个对象是否是一个类的实例:对象 instanceof 构造函数;返回值为 truefalse
所有的对象都是Object的后代,所有任何对象进行 instanceof Object 时,返回的都是 true

原型对象 prototype

将函数定义在全局作用域中会污染全局作用域的命名空间,而且不安全。
自行创建的每一个函数中,都会被解析器添加一个属性 prototype,对应着一个对象,即原型对象。prototype保存了原型对象的地址,是唯一的。当函数作为普通函数调用prototype时,没有任何作用;当函数以构造函数形式调用时,它创建的对象中都会有一个属性prototype,指向该构造函数的原型对象,可以通过__proto__来访问该属性。
原型对象相当于一个公共区域,所有同一个类的实例都可以访问到这个原型对象,因此,可以将所有对象中共有的内容统一设置到原型对象中
当我们访问一个对象的一个属性或方法时,先在对象自身中查找,如果有就直接使用,如果没有就去原型对象中寻找,找到了就直接使用。

function Person(name, age, gender, ads){
	this.name = name;
	this.age = age;
	this.gender = gender;
	this.address = ads;
}
//向原型中添加公共方法
Person.prototype.sayName = function(){
	console.log(this.name);
}
var pers = new Person("kirlant", 16, "female", "empire");
console.log(typeof pers);
console.log(pers);
pers.sayName();

运行结果:

object
Person {
  name: 'kirlant',
  age: 16,
  gender: 'female',
  address: 'empire'
}
kirlant

检查对象自身(而不是原型对象)中是否含有某个属性:对象.hasOwnProperty(属性);返回值为 truefalse
原型对象也是对象,所以原型对象中也有__proto__ ⟶ \longrightarrow 调用一个对象的属性或方法时,先在自身中寻找,找不到就去原型对象中寻找,再找不到则去原型对象的原型对象中寻找,直到找到Object对象的原型。Object对象的原型没有原型,其__proto__属性值对应的是null,Object对象的原型中依然找不到就返回undefined。

toString()

console.log(pers.toString());

运行结果:

[object Object]

可以根据需要重写该函数。

垃圾回收

程序运行过程中会产生垃圾,垃圾积攒过多会导致程序运行时间变慢 ⟶ \longrightarrow 需要一个垃圾回收机制处理程序运行过程中产生的垃圾。
当一个对象没有任何变量或属性对它进行引用,它就变成了垃圾,这种对象过多会占用大量内存导致程序运行变慢,所以需要对它进行清理。JS中有自动的垃圾回收机制,会自动将它们从内存中销毁,我们不需要也不能进行垃圾回收的操作。我们需要做的只是将不再使用的对象设置为null

内建对象

数组 Array

创建数组对象:var arr = new Array();可以在创建时指定数组元素var arr = new Array(1, 2, 3);
添加元素:数组[索引] = 值;
读取元素:数组[索引];如果读取不存在的索引,不会报错而会返回一个undefined。
获取数组长度:数组.length;可以修改数组的长度数组.length = 值;如果修改的长度大于原来的长度,那么多余部分会空出来;如果小于原来的长度,那么多余部分会被删除。向数组的最后一个位置添加元素:arr[arr.length] = 值;
使用字面量创建数组:var arr = [];可以在创建时指定数组元素var arr = [1, 2, 3];
数组中的元素可以是任意数据类型,可以是对象,可以是函数。

数组的常用方法:

  • push() 向数组末尾添加一个或多个元素,并返回数组新的长度;
  • pop() 删除并返回数组的最后一个元素;
  • unshift() 向数组开头添加一个或多个元素,并返回数组新的长度;
  • shift() 删除并返回数组的第一个元素;
  • slice() 从数组中提取指定位置的元素,切片:var get = arr.slice(0,2);索引前闭后开;如果第二个参数不写,那么会截取从start索引开始往后的全部元素;索引如果传递一个负值,则从后往前计算;
  • splice() 删除指定位置的元素,并将被删除的元素作为返回值返回:var del = arr.slice(startIdx, delNums, [addElement1, addElement2, ...]);从startIdx开始,删除delNums个元素,然后在startIdx前插入addElement1, addElement2,…;
  • concat() 连接两个或多个数组,并将新的数组返回;
  • join() 将数组转换为一个字符串,不会对原数组产生影响,而是将转换后的字符串作为结果返回;可以指定一个字符串作为数组中元素的连接符:var result = arr.join(mystr);默认用","连接;
  • reverse() 反转数组,直接修改原数组;
  • sort() 对数组中的元素进行排序,直接修改原数组;默认按照Unicode编码进行排序,因此对数字排序可能得到错误的结果; ⟶ \longrightarrow 添加回调函数指定排序规则:arr.sort( function(a,b){return a-b;} );注意:数组中,a要在b之前;浏览器根据回调函数的返回值决定元素的顺序,如果返回值小于等于0,那么不交换元素位置,如果返回值大于0,那么交换元素位置;

遍历数组
方法一:for

for(var i=0; i<arr.length; i++){
	console.log(arr[i]);
}

方法二:forEach()
\qquad forEach()方法需要一个函数作为参数,该函数由我们创建但不由我们调用,称为回调函数。数组中有几个元素函数就会执行几次,每次都将遍历到的元素以实参的形式传入函数中,因此可以定义形参来读取这些内容。
\qquad 浏览器会向回调函数中传入三个参数:当前遍历到的元素,当前元素的索引,当前正在遍历的数组。

// IE8及以下的浏览器均不支持该方法
arr.forEach(function(value, index, obj){
	console.log(value);
	console.log(index);
	console.log(obj);
});
日期 Date

JS中使用Date对象来表示一个时间。
创建对象:var d = new Date(); 此时默认值为当前代码执行的时间;
创建指定时间对象:var d = new Date("12/03/2016 11:10:30"); 字符串格式:月/日/年 时:分:秒
获取当前日期对象的时间戳:getTime(),从格林威治标准时间1970.01.01 00:00:00 到当前日期花费的毫秒数;计算机底层保存时间时使用的都是时间戳;
获取当前的时间戳:Date.now();

Math

工具类,封装了数学运算相关的属性和方法。
向上取整:Math.ceil()
向下取整:Math.floor()
四舍五入:Math.round()
生成一个0~1之间的随机数:Math.random(),不包括0和1
计算x的y次幂:Math.pow(x,y)

包装类

包装类将基本数据类型转换为对象:String、Number、Boolean。当对一些基本数据类型调用属性和方法时,浏览器会临时使用包装类将其转换为对象,然后调用对象的属性和方法,调用完以后,再将其转换回基本数据类型。

字符串 String

字符串在底层以字符数组的形式保存,因此操作方法和操作数组类似。
属性:length,用来获取字符串的长度;
方法:charAt() 返回字符串中指定位置的字符;
  \qquad \, charCodeAt() 获取指定位置字符的Unicode编码;
  \qquad \, String.fromCharCode() 根据字符编码获取字符;
  \qquad \, indexOf() 检索字符串中是否含有指定内容,返回值为该内容第一次出现的索引,没有则返回-1;可以指定第二个参数为开始查找的位置;
  \qquad \, lastIndexOf() 从后向前检索字符串中是否含有指定内容;
  \qquad \, slice(startIdx, endIdx) 截取指定位置字符串的内容(前闭后开),返回截取的内容,不影响原字符串;endIdx可省略,此时截取从startIdx开始的所有内容;索引若为负数,则从后向前数;
  \qquad \, substring(startIdx, endIdx) 和slice()类似;参数不能传负数,如果传入了负值则默认使用0;会自动调整参数的位置,如果startIdx>endIdx,会自动交换两个参数;
  \qquad \, substr(startIdx, nums) 从startIdx开始截取nums个字符;
  \qquad \, split(str) 以str为拆分位置,拆分字符串为字符串数组;如果传入空串,则会将每个字符都拆分开;
  \qquad \, toUpperCase() 将字符串转换为大写并返回;
  \qquad \, toLowerCase() 将字符串转换为小写并返回;

正则表达式

\qquad 正则表达式定义了一些字符串的规则,计算机根据正则表达式来检查一个字符串是否符合规则,或提取字符串中符合规则的内容。
创建正则表达式对象:var reg = new RegExp("正则表达式", "匹配模式");使用typeof检查正则对象会返回object;匹配模式有两种:i 忽略大小写,g 全局匹配模式;
使用字面量创建正则表达式:var reg = /正则表达式/匹配模式;
举例:

var reg = new RegExp("a", "i");
var reg = /a/i;

正则表达式中的一些逻辑符:
| [] 或;
[a-z] 任意小写字母;
[A-Z] 任意大写字母;
[A-z] 任意字母;
[^ ] 除了括号里的xxx;
[0-9] 任意数字;
[^0-9] 除了数字;
方法:reg.test(str) 检查字符串str是否符合正则表达式reg的规则,返回truefalse
字符串和正则表达式
var str = "1a2b3c4d5e";
方法:str.split();将一个字符串拆分为数组,可以传递一个正则表达式作为参数,方法就会根据正则表达式拆分字符串;不需要设置全局匹配也会全部拆分;
  \qquad \, str.search();搜索字符串中是否含有指定内容,如果找到了就返回第一次出现的位置,如果没有返回-1;可以接收正则表达式;即使设置了全局匹配也只搜索第一个;
  \qquad \, str.match();根据正则表达式将字符串中符合条件内容提取出来;默认情况下只找第一个符合条件的内容,可以设置正则表达式为全局匹配,就能找到所有内容;可以设置多个匹配模式,顺序无所谓;匹配到的内容被封装到一个数组中返回;
  \qquad \, str.replace(被替换内容(可以用正则表达式),新内容); 将字符串中的指定内容替换为新的内容;默认只替换第一个;
正则表达式的语法
量词: 设置一个内容出现的次数
  \qquad \, {n}花括号前的内容恰好出现n次,只对它前面的一个内容起作用;
  \qquad \, {n1,n2}出现n1~n2次;
  \qquad \, {n1, }出现n1次以上;
  \qquad \, (){n}小括号中的内容恰好出现n次;
  \qquad \, + 前面的内容出现至少一次;
  \qquad \, * 前面的内容出现0次或多次,等同于{0, }
  \qquad \, ? 前面的内容出现0次或1次,等同于{0, 1}
  \qquad \, ^ 开头;
  \qquad \, $ 结尾;
如果在正则表达式中同时使用^$,则要求字符串必须完全符合正则表达式。

元字符: 具有特殊意义的字符
  \qquad \, . 任意字符
  \qquad \, \ 转义字符;使用构造函数时,由于它的参数是字符串,而\是一个转义字符,因此在字符串中使用\转义其他字符时需要写\\
  \qquad \, \w 任意字母、数字、_;等同于[A-z0-9_]
  \qquad \, \W 除了字母、数字、_;等同于[^A-z0-9_]
  \qquad \, \d 任意数字;等同于[0-9]
  \qquad \, \D 除了数字;等同于[^0-9]
  \qquad \, \s 空格;
  \qquad \, \S 除了空格;
  \qquad \, \b 单词边界;
  \qquad \, \B 除了单词边界;
单词边界举例:检查是否含有某个单词时,在这个单词前后加上 \b,就不会查到以这个单词为组成部分的更长的单词。即两个\b中间是一个独立的单词。

var reg = /\bchild\b/g;
var find = "hello child";
console.log(reg.test(find)); // true
find = "hello children";
console.log(reg.test(find)); // false

练习:
创建一个正则表达式,检查字符串是否是手机号

// 以1开头,第二位数字只能是3~9,然后跟着9位任意数字,结束
var reg = /^1[3-9][0-9]{9}$/g;
var phone = "18763370911";
console.log(reg.test(phone));

接收一个用户的输入:

var userName = prompt("请输入用户名:");
console.log(userName);

去除字符串前后的空格:
  \qquad \, 使用空串替换空格,注意中间位置的空格不应该去掉。
  \qquad \, 思路:全局匹配开头的一个或多个空格,或结尾的一个或多个空格,都用空串替换。

var userName = "       Garcia Kirlant       ";
userName = userName.replace(/^\s*|\s*$/g,"");
console.log(userName); // Garcia Kirlant

邮件的正则:
  \qquad \, 以任意字母、数字、下划线开头(^),5位以上;
  \qquad \, 一个@
  \qquad \, 网站名称,一次以上的数字或字母;
  \qquad \, 一到两次域名(.com, .cn什么的);每个域名长度为2~5,包括一个.和后面的字母;
  \qquad \, 一个结束符$;

var reg = /^\w{5,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;
console.log(reg.test("2427369255@qq.com")); // true
console.log(reg.test("2427369255@qq.com.3")); // false

文档对象模型 Document Object Model ( DOM )

JS中通过DOM来对HTML文档进行操作。
文档:整个的HTML网页文档;
对象:将网页中的每个部分都转换为了一个对象;之后就可以以面向对象的形式操作网页;
模型:使用模型来表示对象之间的关系,方便我们获取对象;
在这里插入图片描述

节点 Node

     \quad \; \; 节点是构成HTML文档最基本的单元,网页中的每一个部分都可以称为是一个节点,比如:html标签、属性、文本、注释、整个文档……都是节点。
     \quad \; \; 节点的具体类型是不同的:标签-元素节点属性-属性节点文本-文本节点文档-文档节点
     \quad \; \; 节点的类型不同,其属性和方法也不同。

节点的属性:
  • 文档节点:
    nodeName#document
    nodeType: 9
    nodeValue: null
  • 元素节点:
    nodeName: 标签名
    nodeType: 1
    nodeValue: null
  • 属性节点:
    nodeName: 属性名
    nodeType: 2
    nodeValue: 属性值
  • 文本节点:
    nodeName#text
    nodeType: 3
    nodeValue: 文本内容

     \quad \; \; 浏览器已经提供了文档节点对象document,这个对象是window属性,可以在页面中直接使用;文档节点代表的是整个网页。

事件

     \quad \; \; 事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,也就是用户和浏览器之间的交互行为,比如鼠标移动、点击按钮、关闭窗口等。
     \quad \; \; JavaScript 与 HTML 的交互是通过事件产生的,事件发生后需要有一个行为来处理事件。可以在事件对应的属性中设置一些js代码,当事件被触发时执行这些代码,但这种方式导致行为和结构耦合,不推荐使用。最好为事件绑定处理函数来响应事件,事件被触发时调用该响应函数。

文档的加载

浏览器在加载页面时,是按照自上而下的顺序加载的,读取一行运行一行,因此如果将script标签写在页面上部,在代码执行时,页面还没有加载,DOM对象也没有加载,就会导致无法获取DOM对象,事件就不能触发 ⟶ \longrightarrow onload事件在整个页面加载完成后才触发,可以为 window 对象绑定一个 onload 事件,该事件对应的响应函数将会在页面加载完成之后才执行,就能确保在代码执行时所有的DOM对象都加载完毕。
在body的结束标签前一行引入外部.js文件。

window.onload = function(){
	自定义的所有的响应函数
}

innerHTML属性用于获取标签内部的HTML代码,对于自结束标签没有意义。

DOM 增 删 查 改
1. 查询
  • 获取元素节点:通过 document 对象调用
    getElementById() 通过 id 属性获取一个元素节点对象,一定是唯一的;
    getElementsByTagName() 通过标签名获取一组元素节点对象,返回值是一个数组;
    getElementsByName() 通过 name 属性获取一组元素节点对象;
  • 获取元素节点的子节点:通过具体的元素节点调用
    getElementsByTagName() 获取当前标签节点的指定标签名的后代节点;
    childNodes 属性,当前节点的所有子节点,返回值是一个数组;会获取包括文本节点在内的所有节点,在IE8以上的浏览器中,标签之间的空白区域也会被算成一个节点,注意兼容性
    children 属性,获取当前元素的所有子元素
    firstChild 属性,获取当前节点的第一个子节点(包括空白文本节点);
    firstElementChild 属性,获取当前元素的第一个子元素(不支持IE8及以下的浏览器);
    lastChild 属性,获取当前节点的最后一个子节点(包括空白文本节点);
    lastElementChild 属性,获取当前元素的最后一个子元素(不支持IE8及以下的浏览器);
  • 获取父节点兄弟节点:通过具体节点调用
    parentNode 属性,获取当前节点的父节点;
    previousSibling 属性,当前节点的前一个兄弟节点;
    nextSibling 属性,当前节点的后一个兄弟节点;
  • 获取 body 标签document.body
  • 获取 html 根标签document.documentElement
  • 获取所有元素:document.all
  • 根据元素的 class 属性查询一组节点对象:document.getElementByClassName()
  • 根据 CSS 选择器来查询元素节点document.querySelector(),传入参数为 CSS 选择器,比如".box1 div"选择了第一个class=box1的元素下面的第一个divdocument.querySelectorAll()则选择所有符合条件的元素,以数组形式返回
2. 增加
  • appendChild()添加子节点(父节点调用)
  • insertBefore(newNode, chooseNode) 在指定子节点前插入新节点(父节点调用)
  • replaceChild(newNode, chooseNode) 用新节点替换指定子节点(父节点调用)
3. 删除(父节点调用)
  • removeChild(delNode) 删除子节点(父节点调用)
4. 修改(父节点调用)

-利用 innerHTML 属性进行修改

父节点常用 当前节点.parentNode 属性来获取

操作样式
  • 修改样式
    元素.style.样式名 = 样式值(字符串);
    \quad 如果CSS的样式名中含有’-‘需要将其改成驼峰命名法:去掉’-',将后面的第一个字母变成大写。
    \quad 通过style修改的样式都是内联样式,有较高的优先级,修改后会立刻生效。CSS样式中写了!important的属性除外。
  • 读取样式 (只读)
    元素.style.样式名
    \quad 通过style读取的样式都是内联样式,无法读取样式表中的样式。
  • 读取元素当前显示的样式 (只读)
    IE(8及以下)浏览器:元素.currentStyle.样式名
    其他浏览器:getComputedStyle(元素, null) 返回一个对象,该对象封装了元素的所有样式,读取时用 对象.样式名 来获取具体样式,如果获取的样式没有设置,那么会获取到具体的而不是默认的auto
    兼容:自己封装一个函数(呵呵)
//  根据浏览器中有无 getComputedStyle()方法来选择获取方式
// 	obj: 要获取样式的元素
//	name: 要获取的样式名
function getStyle(obj, name){
	// getComputedStyle()方法在 IE8 及以下的浏览器中没有 ->
	// getComputedStyle是一个变量,局部和全局都找不到时会报错;
	// window.getComputedStyle是一个属性,局部和全局都找不到时会返回 undefined,转换为布尔值后就是 false。
	if(window.getComputedStyle){
		return getComputedStyle(obj, null)[name];
	}else{
		return obj.currentStyle[name];
	}
}
  • 其他相关属性 element.属性名
    \quad clientWidth、clientheight 获取元素的可见宽度、高度(包括内容区和内边距),返回值是数字,可以直接进行计算;属性只读,不能修改;
    \quad offsetWidth、offsetHeight 获取元素的整个宽度和高度,包括内容区、内边距和边框;
    \quad offsetParent 获取元素的定位父元素,也就是离当前元素最近的开启了定位的祖先元素;如果所有的祖先元素都没有开启定位,则返回body;
    \quad offsetLeft、offsetTop 当前元素相对于其定位父元素的水平、垂直偏移量;
    \quad scrollWidth、scrollHeight 获取元素整个滚动区域的宽度和高度;
    \quad scrollLeft、scrollTop 获取水平、垂直滚动条滚动的距离;chorm浏览器认为body的滚动条属于body,可以用document.body.scrollTop获取垂直距离;firefox、ie等浏览器认为body的滚动条属于html,要用document.documentElement.scrollTop。垂直距离同理;
    \quad 当满足 scrollHeight - scrollTop == clientheight 时,说明垂直滚动条滚动到底;水平滚动条同理。 用户注册界面常常有不看完协议就不让单击表单项的情况,这是因为在HTML中创建表单项时,disabled 属性为 disabled="disabled"; 表单项不可用;滚动条滚动的时候触发事件 onscroll,判断协议是否被拉到底,拉到底之后设置 disabled=false;令表单项可用。
    其他相关属性
事件对象

\quad 当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数。在事件对象中封装了当前事件的一切相关信息,比如鼠标的坐标、键盘上被按下的键、鼠标滚轮的滚动方向……
\quad 注意:IE8 及以下的浏览器中,事件对象被作为 window 对象的属性 保存。
\quad HTML DOM 事件

  • onmousemove 事件,鼠标在元素中移动时触发;
  • clientX、clientY 事件的属性,获取鼠标相对于可见窗口的坐标;
  • pageX、pageY 事件的属性,获取鼠标相对于整个页面的坐标;

在这里插入图片描述

// 获取各个元素
var divMove = document.getElementById("move");
var divShow = document.getElementById("show");
// 获取div
// 绑定事件
divMove.onmousemove = function(event){
	event = event || window.event; // 兼容性
    var x = event.clientX;
    var y = event.clientY;
    divShow.innerHTML = "x = "+ x + ", y = "+ y;
};
<div class="outer" id="outer">
    <div class="move" id="move"></div>
    <div class="show" id="show"></div>
</div>
// less代码
@fontSize:20px;
@margins:20px;
body{
    width: 600px;
    margin: @margins auto;
    display: flex;
    justify-content: center;
    .outer{
        width: 100%;
        .move{
            width: 100%;
            height: 400px;
            margin-bottom: @margins;
            border: 1px solid rgb(127, 26, 222);
        }
        .show{
            width: 100%;
            height: 40px;
            line-height: @fontSize;
            border: 1px solid rgb(127, 26, 222);
        }
    }
}
事件的冒泡 bubble

\quad 事件的冒泡指事件的向上传导,当后代元素上的事件被触发时,祖先元素的相同事件也会被触发。在开发中,大部分情况下冒泡都是有用的。如果不希望事件冒泡,可以通过事件对象取消冒泡event.cancelBubble=true;

<body id="body">
    <div class="outer" id="outer">
        <div class="inner" id="inner"></div>
    </div>
</body>
// 获取各个元素
var theBody  = document.getElementById("body");
var divOut = document.getElementById("outer");
var divIn = document.getElementById("inner");
// 绑定事件
theBody.onclick = function(event){
    alert("body");
};
divOut.onclick = function(event){
    alert("outer");
};
divIn.onclick = function(event){
	event.cancelBubble=true;
    alert("inner");
};
@length:100px;
body{
    width: @length*3;
    height: @length*3;
    border: 1px solid rgb(127, 26, 222);

    margin: 20px auto;
    display: flex;
    justify-content: center;
    .outer{
        width: @length*2;
        height: @length*2;
        background-color: rgb(200, 235, 255);
        
        margin: auto;
        display: flex;
        justify-content: center;
        .inner{
            width: @length;
            height: @length;
            margin: auto;
            background-color: azure;
        }
    }
}
事件的委派

\quad 只绑定一次事件,即可应用到多个元素上,即使元素是后来添加的。因此可以考虑将事件绑定给这些元素共同的祖先元素上,这样,当后代元素上的事件触发时,会一直冒泡到祖先元素上,从而通过祖先元素的响应函数来处理事件。需要判断触发事件的元素是不是期望的元素。
\quad 通过委派可以减少事件绑定的次数。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <!-- 令视口为完美视口 -->
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>大秦帝国</title>
        <link rel="shortcut icon" href="./imgs/kirlant.ico">
        <link rel="stylesheet" href="./baseCSS/reset.css">
        <link rel="stylesheet" href="./css/all.css">
        <link rel="stylesheet" href="./learn.css">
    </head>
    <body id="body">
        <ul id="list">
            <li><a class="link" href="javascript:;">一方通行</a></li>
            <li><a class="link" href="javascript:;">垣根帝督</a></li>
            <li><a class="link" href="javascript:;">御坂美琴</a></li>
            <li><a class="link" href="javascript:;">麦野沈利</a></li>
            <li><a class="link" href="javascript:;">食蜂操祈</a></li>
            <li><a class="link" href="javascript:;">蓝花悦</a></li>
            <li><a class="link" href="javascript:;">削板军霸</a></li>
        </ul>
        <div class="divBtn">
            <input id="btnAdd" type="button" value="添加">
            <input id="btnBind" type="button" value="绑定">
        </div>
        <script type="text/javascript" src="./learn.js"></script>
    </body>
</html>
// 获取各个元素
var lines  = document.getElementsByTagName("a");
var list = document.getElementById("list");
var btnBind = document.getElementById("btnBind");
var btnAdd = document.getElementById("btnAdd");
// 绑定事件
list.onclick = function(event){
    event = event || window.event;
    if(event.target.className == "link"){
        alert("alert list");
    }
}
// 点击按钮添加超链接
btnAdd.onclick = function(event){
    var newLi = document.createElement("li");
    newLi.innerHTML = "<a class='link' href='javascript:;'>第八人</a>";
    list.appendChild(newLi);
}
@length: 100px;
@fontsize: 25px;
body{
    width: @length*4;
    height: @length*3;
    font-size: @fontsize;
    border: 1px solid rgb(127, 26, 222);
    margin: 20px auto;
    display: flex;
    flex-wrap: wrap;
    justify-content: center; 
    ul{
        width: 100%;
        background-color: rgb(223, 202, 255);
        margin: auto;
        text-align: center;
        display: flex;
        justify-content: center;
        li{
            line-height: @fontsize;
            margin: 10px;
        }
    }
    .divBtn{
        margin: 0 auto;
        input{
            font-size: 20px;
            line-height: 26px;
            text-align: center;
            color: white;
            background-color: rgb(121, 38, 194);
            border: solid 2px rgb(84, 28, 134);
        }
    }
}
事件的绑定

\quad 使用对象.事件 = 函数的形式只能同时为一个元素的一个事件绑定一个响应函数,如果绑定了多个函数,则后面的会覆盖前面的函数 ⟶ \longrightarrow 使用 addEventListener()(不支持IE8及以下)或 attachEvent()(只支持IE8及以下)。

  • addEventListener()先绑定先执行
    参数:
    \quad 事件的字符串,去掉‘on’
    \quad 回调函数,事件触发时调用该函数;
    \quad 是否在捕获阶段触发事件,一般设为false
    this 指向绑定事件的对象;
  • attachEvent()后绑定先执行
    参数:
    \quad 事件的字符串,需要‘on’
    \quad 回调函数,事件触发时调用该函数;
    this 指向window;
// 为一个按钮绑定多个单击响应函数
/* 为一个按钮绑定多个单击响应函数
    obj:要绑定事件的对象
    eventStr:事件名称,不加'on'
    callback:要绑定的回调函数
*/
function bind(obj, eventStr, callback){
    if(obj.addEventListener){
        // 大部分浏览器兼容的方式
        obj.addEventListener(eventStr, callback, false);
    }else{
        /* this 指向谁由调用方式决定 
            IE8及以下浏览器中,让浏览器调用匿名函数,在匿名函数中让obj调用回调函数,
            就能保证不管是什么浏览器,调用 callback 的都是 obj
        */
        // IE8及以下浏览器
        obj.attachEvent("on"+eventStr, function(){callback.call(obj);});
    }
}
bind(btnBind, "click", function(){ alert("first"); });
bind(btnBind, "click", function(){ alert("second"); });
bind(btnBind, "click", function(){ alert("third"); });
事件的传播

微软 事件应该从内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后向祖先元素传播,也就是事件应该在冒泡阶段执行。
网景 事件应该从外向内传播,先触发当前元素最外层的祖先元素事件,再向内传播给后代元素,也就是事件应该在捕获阶段执行。
W3C 综合两个方案,将事件的传播分成三个阶段:
\quad 捕获阶段:从最外层的祖先元素向目标元素进行事件的捕获,默认此时不会触发事件;
\quad 目标阶段:事件捕获到目标元素,捕获结束后开始在目标元素上触发事件;
\quad 冒泡阶段:事件从目标元素向祖先元素传递,依次触发祖先元素上的事件。

\quad 如果希望在捕获阶段触发事件,可以将 addEventListener() 的第三个参数设置为 true,一般不希望在捕获阶段触发事件,所以一般都设为 false。IE8及以下浏览器没有捕获阶段。

滚轮事件

元素.onwheel = function(){},但是在火狐浏览器中需要用addEventListener()绑定DOMMouseScroll事件。
获取滚轮滚动方向:
\quad event.wheelDelta属性,大于0时向上滚动,小于0时向下滚动;
\quad event.detail属性,小于0时向上滚动,大于0时向下滚动;火狐专用
当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动。这是浏览器的默认行为,如果不希望发生这个行为,可以令函数返回值为false火狐需要用event.preventDefault()取消默认行为;IE8会报错,因此需要加一个判断。

<div id="box1"></div>
body{
    height: 2000px;
    div{
    width: 100px;
    height: 100px;
    position: absolute;
    }
    #box1{
        min-height: 100px;
        max-height: 1000px;
        background-color: rgb(194, 223, 247);
    }
}
// 获取各个元素
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
/*
    鼠标滚轮向下滚动时,box1变长;向上滚动时,box1变短
*/
box1.onwheel = function(event){
    // 向上滚动 180
    if(event.wheelDelta > 0 || event.detail < 0){
        box1.style.height = box1.clientHeight - 10 + "px";
    }
    // 向下滚动 -180
    else{
        box1.style.height = box1.clientHeight + 10 + "px";
    }
    event.preventDefault && event.preventDefault();
    return false;
};
键盘事件

键盘事件一般绑定给 可以获取到焦点的对象 或者 document。

  • 某个按键被按下:onkeydown
    \quad 如果按着一个键不松手,它会连续触发。当连续触发时,第一次和第二次之间间隔稍长,其他的间隔则很短,这是为了防止误操作。
  • 某个按键被松开:onkeyup
    \quad 不会连续触发。
  • event 的属性
    \quad key 返回键值,比如按下’y’,返回"y";
    \quad code 返回一个奇怪的东西,比如按下’y’,返回"KeyY";
    \quad shiftKey、ctrlKey、altKey 返回是否按下了这三个键,按下为 true
document.onkeydown = function(event){
    event = event || window.event;
    // 判断y是否被按下
    // if(event.key === "y"){
    //     alert("press a y");
    // }
    // 判断 Y 是否被按下(y和Shift同时被按下)
    if(event.shiftKey && (event.key === "Y")){
        alert("press shiftKey and y");
    }
};

对于输入文本框,输入内容属于 onkeydown 的默认行为,如果取消了默认行为,那么内容不会出现在文本框中。

<input type="text" />
var input = document.getElementsByTagName("input")[0];
var reg = /^[0-9]/i;
input.onkeydown = function(event){
    event = event || window.event;
    // 不让输入数字
    if(reg.test(event.key)){
        return false;
    }
};

浏览器对象模型 Browser Object Model ( BOM )

\quad 提供一组对象,用来完成对浏览器的操作。这些对象在浏览器中都是作为 window 对象的属性保存的,可以通过 window 对象调用,也可以直接使用。

  • Window 整个浏览器的窗口,网页的全局对象;
  • Navigator 当前浏览器的信息,通过该对象来识别不同浏览器;
  • Location 当前浏览器的地址栏信息(最上面显示网址的那个小框框),用来获取地址栏信息或者操作浏览器跳转页面;
  • History 浏览器的历史记录;由于隐私原因,该对象不能获取具体历史记录,只能操作浏览器向前或向后翻页,而且该操作只在当次访问时有效;
  • Screen 用户的屏幕信息,可以获取用户的显示器的相关信息(移动端会用,PC端不常用);
Navigator

\quad 历史原因,大部分属性都没什么用了,只剩一个userAgent来判断浏览器信息了。userAgent是一个字符串,用来描述浏览器。
\quad IE11中和IE相关的标识都去除了,所以不能通过userAgent识别IE浏览器了(卧槽)。Edge浏览器已经变成Chrome内核了:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53

var ua = window.navigator.userAgent;
if(/msie/i.test(ua)){
	 alert("Oh No IE");
}else if(/chrome/i.test(ua)){
    alert("Chorme");
}else if(/firefox/i.test(ua)){
    alert("Firefox");
}

还可以通过一些浏览器中特有的对象来判断浏览器信息,比如ActiveXObject只存在于IE里(哦豁,找到你了)。

if("ActiveXObject" in window){
    alert("ohoo~ IE, I find you");
}
History

操作浏览器向前或向后翻页。

  • length 获取到当前访问的连接数量;
  • back() 回退到上一个页面,和浏览器的后退按钮作用一样;
  • forward() 跳转到下一个页面,和浏览器的前进按钮一样;
  • go() 跳转到指定页面,需要一个整数n做参数,n是跳转页面的个数;n>0时向前跳转,n<0时向后跳转;
<div id="box1">
    <a href="https://www.bilibili.com">哔哩哔哩</a><br>
    <a href="https://www.baidu.com"> 百度 </a><br>
    <a href="https://mp.csdn.net/mp_blog/manage/article">咦?</a><br>
</div>
var btnBack = document.getElementById("back");
var btnFoward = document.getElementById("foward");
btnBack.onclick = function(){
    history.back();
    console.log(history.length);
};
btnFoward.onclick = function(){
    history.forward();
    history.back();
    console.log(history.length);
}
body{
    position: absolute;
    div{
        width: 100px;
        height: 100px;
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        align-content: center;
    }
    #box1{
        background-color: rgb(194, 223, 247);
        a{
            width: 100%;
            font-size: 20px;
            line-height: 20px;
            vertical-align: middle;
            text-align: center;
            margin: 4px auto; 
        }
    }
    #btns{
        background-color: rgb(194, 247, 233);
        input{
            height: 25px;
            font-size: 20px;
            line-height: 20px;
            text-align: center;
    
            border-radius: 7px;
            border: solid 1px rgb(105, 105, 105);
    
            padding: 0 10px;
            margin: 2px auto;
        }
    }
}
Location

\quad 如果直接打印location,则可以获取到浏览器的地址栏信息(当前页的完整路径);如果直接将其修改为一个完整的路径或相对路径,则页面会自动跳转到该路径,并生成相应的历史记录;
在这里插入图片描述

  • location.assign()用来跳转到其他页面,作用和直接修改location一样;
  • location.reload() 用于重新加载当前页面,作用和刷新按钮一样;如果传入true作为参数,则会强制清空缓存,刷新页面;
  • location.replace() 用一个新的页面替换当前页面,调用完毕会跳转页面,不会生成历史记录,不能用回退按钮;
Window
  • 如果希望一段程序每间隔一段时间调用一次,可以使用定时调用setInterval( function(){}, times)
    参数:回调函数;每次调用的间隔时间,整数,单位是mm;
    返回值:一个Number型的整数timer,用来作为定时器的唯一标识,传入clearInterval()来关闭该定时器;
  • 延时调用 setTimeout()函数不马上执行,而是隔一段时间以后再执行,而且只执行一次。参数与定时调用相同。
    延时调用和定时调用是可以互相代替的。
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <!-- 令视口为完美视口 -->
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>大秦帝国</title>
        <link rel="shortcut icon" href="./imgs/kirlant.ico">
        <link rel="stylesheet" href="./baseCSS/reset.css">
        <link rel="stylesheet" href="./css/all.css">
        <link rel="stylesheet" href="./learn.css">
    </head>
    <body id="body">
        <div class="line start"></div>
        <div class="mid">
            <div class="btn">
                <div class="btn1">
                    <button id="btn1Right">向右移动嗷</button>
                    <button id="btn1Left">向左移动嗷</button>
                </div>
                <div class="btn2">
                    <button id="btn2Right">向右移动嗷</button>
                    <button id="btn2Left">向左移动嗷</button>
                </div>
            </div>
            <div class="box" id="box1"></div>
            <div class="box" id="box2"></div>
        </div>
        <div class="line end"></div>
        <script type="text/javascript" src="./learn.js"></script>
    </body>
</html>
// 获取各个元素
var btn1Right = document.getElementById("btn1Right");
var btn1Left = document.getElementById("btn1Left");
var btn2Right = document.getElementById("btn2Right");
var btn2Left = document.getElementById("btn2Left");
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
//  根据浏览器中有无 getComputedStyle()方法来选择获取方式
// 	obj: 要获取样式的元素
//	name: 要获取的样式名
function getStyle(obj, name){
	// getComputedStyle()方法在 IE8 及以下的浏览器中没有 ->
	// getComputedStyle是一个变量,局部和全局都找不到时会报错;
	// window.getComputedStyle是一个属性,局部和全局都找不到时会返回 undefined,转换为布尔值后就是 false。
	if(window.getComputedStyle){
		return getComputedStyle(obj, null)[name];
	}else{
		return obj.currentStyle[name];
	}
};
/*
    尝试创建一个移动 div 的函数
    obj:要移动的对象
    speed:移动速度
    target:移动的目标位置
    dir:移动方向, "left" 或 "top" (height 或者 width 会变得奇怪起来)
    t:移动的间隔时间,mm
    callback:一个函数,动画执行完毕后执行
 */
function move(obj, speed, target, dir, t, callback=function(){}){
    clearInterval(obj.timer);
    // 开启一个定时器来控制div移动方向
    obj.timer = setInterval(function(){
        var oldPos = parseInt(getStyle(obj, dir));
        var useSpeed;
        if(target < oldPos){
            useSpeed = -speed;
        }else{
            useSpeed = speed;
        }
        var newPos = oldPos + useSpeed;
        if((useSpeed > 0 && newPos > target)||(useSpeed < 0 && newPos < target)){
            newPos = target; 
        }
        obj.style[dir] = newPos+"px";
        if(newPos == target){
            clearInterval(obj.timer);
            callback();
        }
    },t);
};
btn1Right.onclick = function(){ 
    move(box1, 20, 900, "left", 20);
};
btn1Left.onclick = function(){
    move(box1, 20, 0, "left", 20);
};
btn2Right.onclick = function(){ 
    move(box2, 40, 900, "left", 20);
};
btn2Left.onclick = function(){
    move(box2, 40, 0, "left", 20);
};
body{
    display: flex;
    justify-content: center;
    .line{
        width: 5px;
        height: 500px;
        background-color: black;
        margin: 10px 0;
    }
    .mid{
        width: 1000px;
        margin: 10px 0;
        position: relative;
        .btn{
            width: 100%;
            height: 32px;
            margin-bottom: 10px;
            position: absolute;

            display: flex;
            flex-wrap: nowrap;
            justify-content: center;
            div{
                margin: 0 5px;
            }
            button{
                height: 32px;
                font-size: 20px;
                line-height: 20px;
                text-align: center;
                padding: 5px 7px;
                margin: 0 3px;
            }
            .btn1 button{
                color: rgb(22, 74, 126);
                border: 1px solid rgb(22, 74, 126);
                background-color: rgb(197, 223, 248);
            }
            .btn2 button{
                color: rgb(22, 88, 13);
                border: 1px solid rgb(22, 88, 13);
                background-color: rgb(232, 255, 212);
            }
        }
        .box{
            width: 100px;
            height: 100px;
        }
        #box1{
            margin-top: 70px;
            background-color: rgb(197, 223, 248);
        }
        #box2{
            margin-top: 20px;
            background-color: rgb(232, 255, 212);
        }
    }
}

类的操作

修改元素样式

\quad 通过style属性来修改元素样式时,每修改一个样式,浏览器就要重新渲染一次页面,这样执行性比较差,而且当需要修改多个样式时很不方便。
⟶ \longrightarrow 一行代码修改多个样式:通过修改元素的className属性来简介修改样式。此时浏览器只需要重新渲染页面一次,性能比较好,并且可以使表现和行为进一步分离。

<button id="btn01">点击按钮,修改box样式</button>
<div id="box" class="b1"></div>
body {
	#btn01{
        width: 200px;
        font-size: 16px;
        margin: 10px;
    }
    .b1{
        width: 100px;
        height: 100px;
        background-color: #296ea3;
        margin: 10px;
    }
    .b2{
        width: 200px;
        height: 200px;
        background-color: #8da8bd;
        margin: 10px;
    }
}
var btn01 = document.getElementById("btn01");
var box = document.getElementById("box");
btn01.onclick = function(){
    // 修改box的样式? No,修改box指向的类
    box.className = "b2";
}

有时候只想在前一个样式的基础上修改几个属性,可以使用:

.b2{
    width: 200px;
    background-color: #8da8bd;
    }
box.className += " b2";
封装成函数
<button id="btn01">点击按钮,添加box样式</button>
<button id="btn02">点击按钮,删除box样式</button>
<button id="btn03">点击按钮,切换box样式</button>
<div id="box" class="b1"></div>
body {
    button{
        width: 200px;
        font-size: 16px;
        margin: 10px;
    }
    .b1{
        width: 100px;
        height: 100px;
        background-color: #296ea3;
        margin: 10px;
    }
    .b2{
        width: 200px;
        background-color: #8da8bd;
    }
}
var btn01 = document.getElementById("btn01");
var btn02 = document.getElementById("btn02");
var btn03 = document.getElementById("btn03");
var box = document.getElementById("box");
btn01.onclick = function(){
    // 修改box的样式? No,修改box指向的类
    if(!hasClass(box, "b2")){
        addClass(box,"b2");
    } 
}
btn02.onclick = function(){
    removeClass(box,"b2");
}
btn03.onclick = function(){
    toggleClass(box,"b2");
}
// 定义一个函数,用来向元素中添加指定的class属性值
function addClass(obj, cn){
    obj.className += " "+cn;
}
// 判断一个元素中是否含有指定的class属性值
function hasClass(obj, cn){
    var reg = new RegExp("\\b"+cn+"\\b");
    if(reg.test(obj.className)){
        return true;
    }else{
        return false;
    }
}
// 删除元素中指定的class属性
function removeClass(obj, cn){
    var reg = new RegExp("\\b"+cn+"\\b");
    obj.className = obj.className.replace(reg, "");
}
// 切换一个类
// 如果元素中具有该类,则删除;如果元素中没有该类,则添加
function toggleClass(obj, cn){
    if(hasClass(obj, cn)){
        removeClass(obj, cn);
    }else{
        addClass(obj, cn);
    }
}

JS对象表示法 JavaScript Object Notation(JSON)

JSON就是一个特殊格式的字符串,可以被任何语言识别,并转换为任何语言中的对象。JSON主要用来进行不同语言之间数据的交互。
JSON和JS对象的格式一样,只是属性名必须加双引号,其他的和JS语法一致。
JSON分类:对象 { };数组 [ ]
JSON中允许的值:字符串、数值、布尔值、null、对象、数组;不能传函数嗷

  • JSON工具类
    将JSON字符串转换为JS对象:JSON.parse();
    将JS对象转换为JSON字符串:JSON.stringify();

练习

1. 图片切换

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <!-- 令视口为完美视口 -->
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>大秦帝国</title>
        <link rel="shortcut icon" href="./imgs/kirlant.ico">
        <link rel="stylesheet" href="./baseCSS/reset.css">
        <link rel="stylesheet" href="./css/all.css">
        <link rel="stylesheet" href="./learn.css">
    </head>
    <body>
        <div class="image">
            <img src="./imgs/bf_3.jpg" />
            <button id="last">last</button>
            <button id="next">next</button>
        </div>
        <script type="text/javascript" src="./learn.js"></script>
    </body>
</html>
var paths = ["./imgs/bf_3.jpg","./imgs/ssm_3.jpg","./imgs/xh_3.jpg"];
var idx = 0;
var nums = paths.length;
// 获取两个按钮
var btnLast = document.getElementById("last");
var btnNext = document.getElementById("next");
// 为两个按钮绑定单击响应函数
btnLast.onclick = function(){
    var change = document.getElementsByTagName("img")[0];
    idx = (idx+nums-1)%nums;
    change.src = paths[idx];
};

btnNext.onclick = function(){
    var change = document.getElementsByTagName("img")[0];
    idx = (idx+1)%nums;
    change.src = paths[idx];
};
body {
  width: 500px;
  height: 500px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
}
.image {
  width: 300px;
  margin: 100px 100px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.image img {
  width: 90%;
  margin: 20px 5%;
}
.image button {
  width: 20%;
  color: #353535;
  font-size: 20px;
  line-height: 20px;
  text-align: center;
  border-radius: 7px;
  border: solid 1px #696969;
  background-color: #c4c4c4;
  margin: 0 7%;
}
2. 选择

在这里插入图片描述

@fontSize:20px;
body{
    // width: 600px;
    height: 500px;
    margin: 0 auto;
    display: flex;
    justify-content: center;
}
.test{
    // width: 100%;
    margin: 100px 100px;

    font-size: @fontSize;

    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-content: center;

    .first,#f2,#f3{
        width: 80%;
        height: @fontSize;
        margin: 10px;

        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        align-content: center;
        div{
            margin: 0 10px;
        }
        .btn{
            height: 30px;
    
            color: rgb(53, 53, 53);
            font-size: @fontSize;
            line-height: @fontSize;
            text-align: center;
    
            border-radius: 7px;
            border: solid 1px rgb(105, 105, 105);

            padding: 0 10px;
            margin: 0 10px;
        }
    }  
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <!-- 令视口为完美视口 -->
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>大秦帝国</title>
        <link rel="shortcut icon" href="./imgs/kirlant.ico">
        <link rel="stylesheet" href="./baseCSS/reset.css">
        <link rel="stylesheet" href="./css/all.css">
        <link rel="stylesheet" href="./learn.css">
    </head>
    <body>
        <div class="test">
            <div class="first">
                你爱好的运动是?
                <form id="f1" action="" method="post"><input id="choose" type="checkbox" name="choose" value="allOrNone" />全选/全不选</form>
            </div>
            <form id="f2" action="" method="post">
                <div name="ins"><input type="checkbox" name="sports" value="basketball" />篮球</div> 
                <div name="ins"><input type="checkbox" name="sports" value="football" />足球</div>
                <div name="ins"><input type="checkbox" name="sports" value="badminton" />羽毛球</div>
                <div name="ins"><input type="checkbox" name="sports" value="pingpang" />乒乓球</div>
            </form>
            <form id="f3" action="" method="post">
                <input class="btn" id="all" type="button" value="all">
                <input class="btn" id="none" type="button" value="none">
                <input class="btn" id="reverse" type="button" value="reverse">
                <input class="btn" id="submit" type="button" value="submit">
                <input class="btn" id="add" type="button" value="add">
                <input class="btn" id="replace" type="button" value="replace">
            </form>
        </div>
        <script type="text/javascript" src="./learn.js"></script>
    </body>
</html>
body {
  height: 500px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
}
.test {
  margin: 100px 100px;
  font-size: 20px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
}
.test .first,
.test #f2,
.test #f3 {
  width: 80%;
  height: 20px;
  margin: 10px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
}
.test .first div,
.test #f2 div,
.test #f3 div {
  margin: 0 10px;
}
.test .first .btn,
.test #f2 .btn,
.test #f3 .btn {
  height: 30px;
  color: #353535;
  font-size: 20px;
  line-height: 20px;
  text-align: center;
  border-radius: 7px;
  border: solid 1px #696969;
  padding: 0 10px;
  margin: 0 10px;
}
/*# sourceMappingURL=./learn.css.map */
// 获取按钮
var btnAll = document.getElementById("all");
var btnNone = document.getElementById("none");
var btnRev = document.getElementById("reverse");
var btnSub = document.getElementById("submit");
var btnAdd = document.getElementById("add");
var btnRep = document.getElementById("replace");
var choose = document.getElementById("choose");
var items = document.getElementsByName("sports");
var f2form = document.getElementById("f2");
var inserts = document.getElementsByName("ins");
var str = [];
// 为按钮绑定单击响应函数
btnAll.onclick = function(){
    for(var i=0; i<items.length; ++i){
        items[i].checked = true;
    }
    choose.checked = true;
};

btnNone.onclick = function(){
    for(var i=0; i<items.length; ++i){
        items[i].checked = false;
    }
    choose.checked = false;
};
btnRev.onclick = function(){
    for(var i=0; i<items.length; ++i){
        items[i].checked = !items[i].checked;
    }
};

btnSub.onclick = function(){  
    for(var i=0; i<items.length; ++i){
        if(items[i].checked){
            str.push(items[i].value);
        }
    }
    if(str.length==0){
        str.push("choose nothing");
    }
    alert(str);
    str = [];
};
btnAdd.onclick = function(){
    var addStr = prompt("请输入待添加节点名及其value,以\" \"隔开(如 游泳 swimming):");
    var sportName = addStr.split(' ');
    // 创建"游泳"节点,添加到 id="f2" 的 form下
    // <div><input type="checkbox" name="sports" value="basketball" />篮球</div>
    // 1.创建div元素节点
    var swim = document.createElement("div");
    swim.name = "ins";
    // 2.创建 input 节点
    var inp = document.createElement("input");
    inp.type = "checkbox";
    inp.name = "sports";
    inp.value = sportName[1];
    // 3.创建文本节点
    var txt = document.createTextNode(sportName[0]);
    // 4.建立父子节点关系
    swim.appendChild(inp);
    swim.appendChild(txt);
    // 5.选择插入位置
    var addIdx = prompt("请输入插入位置(第几个,如 1):");
    f2form.insertBefore(swim,inserts[addIdx-1]);
    // 6. 更新节点
    inserts = document.getElementsByName("ins");
};
btnRep.onclick = function(){
    var addStr = prompt("请输入待添加节点名及其value,以\" \"隔开(如 游泳 swimming):");
    var sportName = addStr.split(' ');
    // 创建"游泳"节点,添加到 id="f2" 的 form下
    // <div><input type="checkbox" name="sports" value="basketball" />篮球</div>
    // 1.创建div元素节点
    var swim = document.createElement("div");
    swim.name = "ins";
    // 2.创建 input 节点
    var inp = document.createElement("input");
    inp.type = "checkbox";
    inp.name = "sports";
    inp.value = sportName[1];
    // 3.创建文本节点
    var txt = document.createTextNode(sportName[0]);
    // 4.建立父子节点关系
    swim.appendChild(inp);
    swim.appendChild(txt);
    // 5.选择替换位置
    var addIdx = prompt("请输入要替换的节点位置(第几个,如 1):");
    f2form.replaceChild(swim,inserts[addIdx-1]);
    // 6. 更新节点
    inserts = document.getElementsByName("ins");
};
// 获取单选框
choose.onclick = function(){
    for(var i=0; i<items.length; ++i){
        items[i].checked = this.checked;
    }
};
// 为每一个多选框都判断一次是否进行了全选
for(var i=0; i<items.length; ++i){
    items[i].onclick = function adjust(){
        var nums = 0;
        var items = document.getElementsByName("sports");
        for(var i=0; i<items.length; ++i){
            if(items[i].checked){
                ++nums;
            }
        }
        if(nums==items.length){
            choose.checked = true;
        }else{
            choose.checked = false;
        }
    };
}
3. 拖拽
<div id="box1"></div>
<div id="box2"></div>
body{
    div{
    width: 100px;
    height: 100px;
    position: absolute;
    }
    #box1{
        background-color: rgb(194, 223, 247);
    }
    #box2{
        background-color: rgb(218, 255, 223);
    }
}
// 获取各个元素
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
/* 拖拽 box 元素
    1. 鼠标按下时,开始拖拽
    2. 鼠标移动时,元素跟随鼠标移动
    3. 鼠标松开时,元素停在该位置
*/ 
box1.onmousedown = function(event){
    event = event || window.event;
    // 偏移量 = 鼠标当前位置 - 元素当前位置
    var diffX = event.clientX - box1.offsetLeft;
    var diffY = event.clientY - box1.offsetTop;
    // 鼠标移动时,修改元素位置,绑定给 box 的父元素
    document.onmousemove = function(event){
        event = event || window.event;
        // 计算元素应该去的位置
        var mouseX = event.clientX - diffX;
        var mouseY = event.clientY - diffY;
        
        box1.style.left = mouseX + "px";
        box1.style.top = mouseY + "px";
    }
    // 鼠标松开时,元素停止移动,固定在当前位置,也就是取消移动事件,同时取消松开事件
    document.onmouseup = function(){
        document.onmousemove = null;
        document.onmouseup = null;
    }
    return false;
}
box2.onmousedown = function(event){
    event = event || window.event;
    // 偏移量 = 鼠标当前位置 - 元素当前位置
    var diffX = event.clientX - box2.offsetLeft;
    var diffY = event.clientY - box2.offsetTop;
    // 鼠标移动时,修改元素位置,绑定给 box 的父元素
    document.onmousemove = function(event){
        event = event || window.event;
        // 计算元素应该去的位置
        var mouseX = event.clientX - diffX;
        var mouseY = event.clientY - diffY;
        
        box2.style.left = mouseX + "px";
        box2.style.top = mouseY + "px";
    }
    // 鼠标松开时,元素停止移动,固定在当前位置,也就是取消移动事件,同时取消松开事件
    document.onmouseup = function(){
        document.onmousemove = null;
        document.onmouseup = null;
    }
    return false;
}

当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖拽功能异常。如果不希望发生这个行为,可以通过 return false; 来取消这个行为(IE8有毒吧???)。

4. 键盘移动小方块
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <!-- 令视口为完美视口 -->
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>大秦帝国</title>
        <link rel="shortcut icon" href="./imgs/kirlant.ico">
        <link rel="stylesheet" href="./baseCSS/reset.css">
        <link rel="stylesheet" href="./css/all.css">
        <link rel="stylesheet" href="./learn.css">
    </head>
    <body id="body">
        <div id="box1"></div>
        <script type="text/javascript" src="./learn.js"></script>
    </body>
</html>
body {
  position: absolute;
}
body div {
  width: 100px;
  height: 100px;
  position: relative;
  background-color: #c2dff7;
}
// 获取各个元素
var box = document.getElementById("box1");
var speed = 10;
var dir = "nomove";
// 开启一个定时器来控制div移动方向
setInterval(function(){
    switch(dir){
        case "ArrowUp":
            box.style.top = box.offsetTop - speed + "px";
            break;
        case "ArrowDown":
            box.style.top = box.offsetTop + speed + "px";
            break;
        case "ArrowLeft":
            box.style.left = box.offsetLeft - speed + "px";
            break;
        case "ArrowRight":
            box.style.left = box.offsetLeft + speed + "px";
            break;
    }
},200);
document.onkeydown = function(event){
    event = event || window.event;    
    if(event.ctrlKey){
        speed  = 50;
    }else{
        speed = 10;
    }
    dir = event.key;
};
document.onkeyup = function(){
    dir = "nomove";
};
5. 图片定时自动切换

开启一个定时器,实现图片的自动切换。
每点击一次按钮就会开启一个定时器,这样开启多个定时器之后,图片切换的速度会非常快;而且即使按了停止按钮,也只能关掉最后的那个定时器,前面打开的无法再关闭 ⟶ \longrightarrow 在开启定时器之前,需要将当前元素上的其他定时器关闭。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <!-- 令视口为完美视口 -->
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>大秦帝国</title>
        <link rel="shortcut icon" href="./imgs/kirlant.ico">
        <link rel="stylesheet" href="./baseCSS/reset.css">
        <link rel="stylesheet" href="./css/all.css">
        <link rel="stylesheet" href="./learn.css">
    </head>
    <body>
        <div class="image">
            <img id="imgs" src="./imgs/bf_3.jpg" />
            <button id="start">start</button>
            <button id="stop">stop</button>
        </div>
        <script type="text/javascript" src="./learn.js"></script>
    </body>
</html>

css代码同练习一。

var img = document.getElementById("imgs");
var btnStart = document.getElementById("start");
var btnStop = document.getElementById("stop");
var paths = ["./imgs/bf_3.jpg","./imgs/ssm_3.jpg","./imgs/xh_3.jpg"];
var nums = paths.length;
var idx = 0;
var times = 0;
btnStart.onclick = function(){
    clearInterval(times);
    times = setInterval(function(){
        ++idx;
        idx %= nums;
        img["src"] = paths[idx];
    },1000);
};
btnStop.onclick = function(){
    clearInterval(times);
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值