JavaScript

JS基础

1、JavaScript输入输出语句

方法:

  • alert (msg):浏览器弹出警示框(归属为为浏览器)

  • console.log(msg):浏览器控制台输出打印信息(归属为浏览器)

  • prompt(info): 浏览器弹出输入框,用户可以进行输入(归属为浏览器)

  • document.write(“”):浏览器页面输出 字体

1
2
3
4
5
6
7
8
9
10
<script>
//这是一个输入框
var a=prompt('请输入你的年龄');
//alert 弹出警示框
alert('计算的结果是');
//console控制台输出给程序员测试用的
console.log("程序员看到的");
//浏览器中可以看到的
document.write("浏览器页面中可以直接看到的");
</script>

image-20221022115408299

image-20221022115429310

image-20221022115435633

image-20221022115446959

2、JS代码的编写位置

1、JS代码可以编写到Onclick属性中

1
<button onclick="alert('别特么点我')">别点我</button>

image-20221022120102189

2、可以将JS代码写到超链接href中当点击超链接时会执行JS代码

1
<a  href="javascript:alert('让你点你就点啊');">点我一下试试</a>

3、外部引入

我们外部的JS文件

1
alert("Hello outer.js");

HTML调用

1
2
3
<head>
<script type="text/javascript" src="outer.js"></script>
</head>

JS数值类型

  • String 字符串
  • Number 数值类型
  • Boolean 布尔类型
  • Null 控制
  • Undefined 未定义
  • Object 对象

双引号中不能放双引号,单引号中不能放反引号

例如: console.log(“今天天气:“真不错””); 这样被浏览器解析出来的就是 “今天天气:” 真不错 “” 被分成了三部分,而浏览器无法解析(真不错)这一标识符

但可以用转义字符来表示 “ 仅为单 个双引号

例如

1
document.write("我擦66:\"真6\"");

image-20221022150103711

JS用于检查一个变量的数值类型 用 typeof

image-20221022150608616

JS中表示数字最大值:Number.MAX_VALUE

正无穷可以用Infinity -Infinity表示负无穷 NaN表示为非Number类型

typeof Infinity 输出结果为Number

String()和Number()强转 和Javaee一样,当非数字字符串调用函数Number()时会报错 NaN,Boolen类型的数值 true会转化成1 false转化成0

如果字符串为类似a=“123a456”,可以用方法a=parseInt(a),输出结果为123,相同的面对a=“123.456a546b”时可以调用a=parseFloat(a) 就会输出123.456

数字进制:

  • 0x开头的数字都为16进制数字
  • 0开头的数字都为8进制数字
  • 0b开头的为2进制数字

1
2
3
4
5
6
var a=0x1ff
var b=010
var c=0b100
console.log(a);
console.log(b);
console.log(c);

image-20221022202609941

Boolen()强转,NaN,0, “” (空串),null,undefined强转为FALSE其他为true

3、数据运算

和Java的有些类似

var a=”123”+”456”;

console.log(a);

image-20221022230843169

任何值和字符串相加都是将其变成字符串然后拼接成新一个新的字符串

若是数字字符串那么就将字符串变成整数然后相乘变成整数

image-20221023111551267

break和continue的区别

  • break是结束这一层的循环,例如for循环,(break下的代码不执行)直接跳出该循环
  • continue是结束这一次的循环进入下一次,本次循环中的continue下的代码不执行

4、对象

JS创建对象的方法和java创建对象的方法类似

1
var objcet=new Object();

而添加属性的方法和Java大不相同,由于JS没有类所以,在创建对象后,可以直接定义属性

1
2
3
4
var objcet=new Object();
objcet.name="张锋";
objcet.age=20;
console.log(objcet);

image-20221023140221957

对象的属性名不强制要求非要为非标识符

我们也可以

1
2
3
4
objcet.name="张锋";
objcet.age=20;
objcet.var=13123;
console.log(objcet);

image-20221023140517791

我们命名一些比较奇怪的对象属性时 无法使用 “对象 .” 的这种形式,但可以使用

1
objcet["2傻子"]="张慧敏";//对象["属性名"]=属性值  

image-20221023140756987

也可以这样取创建对象并添加其属性

1
2
3
4
5
var objcet={
name:"张锋",
age:20,
gender:"男"
};

image-20221023142023175

5、函数

函数也是一个对象,当创建一个函数时,将以字符串的形式封装的代码,输出函数时,函数并不会执行其所封装的代码而是,直接输出其中的内容,只有当调用函数的时候函数中的代码才会执行

1
2
3
4
function fun(){
alert("nb666");
}
console.log(fun);

image-20221023143157785

1
2
3
4
function fun(){
alert("nb666");
}
fun();

image-20221023143115346

JS中也可以在函数中添加形参

1
2
3
4
5
function fun(a,b){

alert(a+b);
}
console.log(fun(150,60));

image-20221023143730635

若在调用函数时,添加的参数多余实参,那么函数只按照所定义的形参的数量取接受参数,若多余,则无视其他多余的,若少于则会输出undifined

对于返回值,我们可以将函数中的输出结果return回去,然后用参数结构返回值,对函数的返回值进行处理

当我们有一个函数只想调用一次,然后弃用,我们可以使用立即函数的方法

首先我们没有其函数名但是我们有函数体,直接小括号包围函数体然后 (函数体)()就可以立即执行函数

1
2
3
(function(){
alert("666");
})();//无参函数

image-20221023150040643

1
2
3
(function(a,b){
alert(a+b);
})(12,13);//带参函数

image-20221023150309148

方法

如果一个对象他的一个属性是一个函数那么这个属性就被我们叫做方法,方法在调用的时候需要我们在对应的属性后加()

1
2
3
4
5
6
7
8
var object={
name:"张锋",
age:18,
behavior:function(){
alert("666");
}
}
object.behavior();

image-20221023151347658

枚举对象 (for 变量 in 对象)

1
2
3
4
5
6
7
8
9
10
var object={
name:"张锋",
age:18,
behavior:function(){
alert("666");
}
}
for(var n in object){
console.log(n);
}

image-20221023152048254

如何输出 对象中的对象名及其属性

1
2
3
4
for(var n in object){
document.write(n);
document.write(":"+object[n]+"<br />")
}

image-20221023152421486

解析器在调用函数的时候每次都会向函数里传递一个隐含参数,这个参数就是this,this指向的是一个对象,这个对象被我们称为函数执行的上下文对象,根据函数的调用方式不同,this会指向不同的方向:

  1. 以函数的形式调用时,this永远是window

    1. ```js
      function fun(){
      console.log(this);
      console.log(this.name);
      }
      var name=”张慧敏”;
      var a=fun;
      a();
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16

      ![image-20221023230107797](https://img.hasdsd.cn/imgimage-20221023230107797.png)

      2. 以方法的形式调用,this就是Object

      ```js
      function fun(){
      console.log(this);
      console.log(this.name);
      }
      var zf={
      name:"张锋",
      age:18,
      sum:fun
      }
      zf.sum();

image-20221023230159313

用工厂方法创建对象

1
2
3
4
5
6
7
8
9
function createperson(name,age,gender){
var person=new Object();
person.name=name;
person.age=age;
person.gender=gender;
return person;
}
var person1=createperson("张锋",20,"男");
console.log(person1);

输出结果为

image-20221024170227897

用函数创建对象(和Java的有参构造的方法很像)

1
2
3
4
5
6
function person(name,age){
this.name=name;
this.age=age;
}
var person1=new person("张锋",20);
console.log(person1);

image-20221024171956935

如何判断这个对象是否是另一个类的的原型对象、

1
2
3
4
5
6
 function person(name,age){
this.name=name;
this.age=age;
}
var person1=new person("张锋",20);
console.log(person1.__proto__==person.prototype);

其中person1为实例对象,而person为原型对象,其输出结果为true

查看一个对象中是否含有此属性可以用方法

对象名.hasOwnProperty(“属性名”)

1
2
3
4
5
6
function person(name,age){
this.name=name;
this.age=age;
}
var person1=new person("张锋",20);
document.write(person1.hasOwnProperty("age"));

输出结果为

image-20221024175617598

当我们直接输出一个对象的时候,我们会得到这样的结果image-20221024180437099

实际上它是调用了方法对象.toString,我们可以重写ToString方法使得我们在直接输出对象的时候得到我们想要的结果

所以

1
2
3
4
5
6
7
8
 function person(name,age){
this.name=name;
this.age=age;
this.toString= function(){
return "person:[name="+this.name+",age="+this.age+"]"}
}
var person1=new person("张锋",20);
document.write(person1);

我们可以在对象一开始创建的时候重写toString方法,指定它的输出内容

6、数组

数组定义的方法

1
2
3
4
5
var arr=new Array();
arr[0]=1;
arr[1]=2;
arr[2]=3;
document.write(arr);

输出结果为

image-20221025004358921

获取数组长度

数组名.length,但当使用该方法的时候,若面对一个非连续数组例如a[0]=1;a[10]=1;那么他输出的结果就是该数组最大索引+1(11);

数组的长度可以随意的修改,倘若修改成大于原长度的数,那么输出数组时,除原数组外其他的元素变为空

​ 倘若修改成小于原长度的数,那么输出数组时,除原数中多余的元素会被删除

也可以这么定义数组

1
2
3
  var a=[1,2,3]; 
//或者
var arr=new Array(1,2,3);

数组里可以塞任意数据类型的数据

1
2
var a=[1,"这他妈的",true];
document.write(a);

image-20221025010056337

数组方法

  • push 向数组末加入一个或多个元素,并返回新数组长度
  • pop 该方法可以删除数组中的最后一个元素,并返回删除的元素
  • unshift 向数组开头处添加一个或多个元素,并返回新数组的长度(开头插入长度后,原先的数组中索引所能得到的元素的值会改变)
  • shift 删除数组开头的第一个元素,并返回删除元素

数组遍历

  • for循环遍历
  • forEach遍历( 对于IE浏览器而言,只支持IE8以上的浏览器)
    • forEach()方法遍历需要函数作为参数
    • 由我们创建但不为我们调用的称为回调函数(function()为回调函数)
    • 数组中有几个元素函数就会执行几次,每次执行时,浏览器就会将我们遍历到的元素以实参的形式传递进来,我们可以用形参来读取这些内容
1
2
3
4
5
var arr=["孙悟空","猪八戒","沙僧","唐僧","白龙马"];
arr.forEach( function(){
console.log("hello");
}
);

image-20221025142914025

回调函数中需要有三个形参来接受实参,第一个参数为数组中正在遍历的元素,第二个参数为数组中的正在遍历 索引。第三个参数为数组中的所有元素

1
2
3
4
5
6
7
var arr=["孙悟空","猪八戒","沙僧","唐僧","白龙马"];
arr.forEach( function(a,b,c){
console.log("a="+a);
console.log("b="+b);
console.log("c="+c);
}
);

image-20221025143253578

数组截取

数组对象中有一个方法 slice(a,b),该方法可以截取数组中的索引所对应的元素 [a,b),不改变原数组,而是拿出新数组来接收所截取的元素

1
2
3
var arr=["孙悟空","猪八戒","沙僧","唐僧","白龙马"];
var arr2=arr.slice(0,2);
console.log(arr2);

image-20221025145238441

倘若我们只添加一个参数,那么slice()方法会将该索引及该索引后的所有元素全部截取

1
2
3
ar arr=["孙悟空","猪八戒","沙僧","唐僧","白龙马"];
var arr2=arr.slice(0);
console.log(arr2);

image-20221025145618310

倘若我们将添加的参数变为负数,那么slice(a,-b)方法就会将索引a到倒数第b+1个元素截取

1
2
3
var arr=["孙悟空","猪八戒","沙僧","唐僧","白龙马"];
var arr2=arr.slice(0,-1);
console.log(arr2);

image-20221025150147262

另一个方法splice(a,b)会将 索引[a,b] 的元素在原数组中删除,并作为结果返回

1
2
3
4
var arr=["孙悟空","猪八戒","沙僧","唐僧","白龙马"];
var arr2=arr.splice(0,2);
console.log(arr);
console.log(arr2);

image-20221025150622608

数组的其他方法

  • 数组的链接:数组1.concat(数组2) 该方法将参数数组接入到本数组的结尾进行拼接,不改变原数组和参数数组并返回一个新数组

    • ```js
      var arr=[“孙悟空”,”猪八戒”,”沙僧”];
      var arr2=[“唐僧”,”白龙马”];
      var arr3=arr.concat(arr2);
      console.log(arr3);
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10

      - ![image-20221025160158063](https://img.hasdsd.cn/imgimage-20221025160158063.png)

      - 数组字符串化
      - 将本数组的所有元素变为一个字符串,join()元素与元素之间用 , 分割,若join()方法中没有参数那么默认为, 若有参数则用参数作为分隔符

      ```js
      var arr=["孙悟空","猪八戒","沙僧"];
      var a=arr.join("---");
      document.write(a);

image-20221025161354625

  • 数组中元素颠倒

    • reverse()方法
  • 数组排序

    • sort方法 根据默认Unicode规则进行排序,改变了原数组的元素位置,没有返回新数组
1
2
3
4
5
var arr=["b","c","a"];
document.write(arr);
document.write("----------");
arr.sort();
document.write(arr);

image-20221025163555354

  • 自定义数组排序

    ​ 若要从小到大则返回a-b,若返回从大到小则返回b-a

1
2
3
4
5
6
7
8
9
10
11
var arr=[1,23,12,31,3,12,31,24,34,5,36,634,23123];
arr.sort( function(a,b){
return a-b;
}
);
document.write(arr+"<br />");
arr.sort( function(a,b){
return b-a;
}
);
document.write(arr);

输出结果为

image-20221025165718177

call和apply

call和apply都需要函数对象来调用,函数对象并非为 fun() 这个是函数,函数对象为fun,call和apply都可以调用函数使用,这两个方法可将一个对象指定成为一个参数,此时这个对象就变成了我们函数中的指定对象this

1
2
3
4
5
6
function fun(){
alert(this.name);
}
var obj={name:"张锋"}
var obj2={}
fun.call(obj);

image-20221026004357552

当一个对象中的属性有方法,这时用对象调用方法后调用call(指定对象),就可以将这个对象中的this变成 指定对象

1
2
3
4
5
6
7
8
var obj={
name:"张锋",
sayname:function() {
alert(this.name)
}
};
var obj2={name:"张慧敏"};
obj.sayname.call(obj2);

image-20221026005154241

call方法可以将实参在对象之后依次传递 ,但apply需要传递实参的话需要将加入的参数变为数组的形式

1
2
3
4
5
6
7
8
9
10
11
var obj={
name:"张锋",
sayname:function(a,b) {
document.write("a="+a+"<br />");
document.write("b="+b+"<br />");
document.write(this.name);
}
};
var obj2={name:"张慧敏"};
obj.sayname.call(obj2,1,2);

image-20221026005536542

1
2
3
4
5
6
7
8
9
10
var obj={
name:"张锋",
sayname:function(a,b) {
document.write("a="+a+"<br />");
document.write("b="+b+"<br />");
document.write(this.name);
}
};
var obj2={name:"张慧敏"};
obj.sayname.apply(obj2,[1,2]);

image-20221026005747912

arguments(封装实参的对象)

arguments是一个类数组对象,他也可以通过索引来操作数据,也可获取长度,arguments中有一个属性callee,可以返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文

1
2
3
4
5
6
function fun(){
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments.callee);
}
fun("hello",132);

image-20221026011429078

Date 日期对象

创建一个当前时间的日期对象

1
2
var date=new Date();
alert(date);

image-20221026013049706

创建一个指定时间的日期对象(月/日 年 时:分:秒)

1
2
var date=new Date("10-26-2022 1:30:22");
alert(date);

image-20221026013247410

Date对象中的一些方法

  • getDate(): 返回该日期对象中的日

    1
    2
    var date=new Date("10-26-2022 1:30:22");
    alert(date.getDate());

    image-20221026013509717

  • getDay(),返回该日期对象所对应的周几(0表示周日,其他的按照数字对应的就是周几)

    • ```js
      var date=new Date(“10-26-2022 1:30:22”);
      alert(date.getDay());
      1
      2
      3
      4
      5
      6
      7
      8

      - ![image-20221026013631381](https://img.hasdsd.cn/imgimage-20221026013631381.png)

      - getMonth 返回该日期对象所对应的是几月(0表示1月 ,1表示2月以此类推)

      - ```js
      var date=new Date("10-26-2022 1:30:22");
      alert(date.getMonth());

image-20221026013857874

  • getFullYear 返回该日期对象的年份

    • ```js
      var date=new Date(“10-26-2022 1:30:22”);
      alert(date.getFullYear());
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23

      -

      ![image-20221026014030514](https://img.hasdsd.cn/imgimage-20221026014030514.png)

      - getTime 返回一个时间戳 1970年1月1日 0时0分0秒,到日期函数所走过的毫秒数
      - now 返回当前时间的时间戳

      #### 包装类对象

      JS为我们提供了三个包装类,可以将三个包装可以将基本数据类型转化为对象

      - String 可以将基本数据类型字符串转化成String对象
      - Number 可以将基本数据类型字符串转化成Number对象
      - Boolen 可以将基本数据类型字符串转化成Boolen对象

      ### 7、字符串

      字符串的底层是由一个字符数组组成,数组中的每一位代表着字符串的一个字符

      ```js
      var a="Hello";
      console.log(a[1],a[2]);

image-20221026130542211

字符串存在许多方法

  • length 返回字符串长度

  • charAt[i] 获取字符串i索引对应的字符

  • charCodeAt[i] 获取字符串i索引对应的字符串的Unicode值

  • concat(字符串2) 与字符串2进行拼接

1
2
3
var a="Hello";
var b="张锋"
console.log(a.concat(b));

image-20221026132343855

  • indexof(“字符”) 检索字符串是否含有字符,若有则返回第一个被检索到的该字符的索引,若该字符是个字符串,则返回被检索到的该字符串的首字母索引,若没有检索到,则返回-1
1
2
var a="Hello"; 
console.log(a.indexOf("o"));

image-20221026132749811

1
2
var a="Hello"; 
console.log(a.indexOf("lo"));

image-20221026133040734

indexof(“字符”,索引) 第二个参数索引被指定为从此索引开始往后检索

1
2
var a="Helloe"; 
console.log(a.indexOf("e"));

image-20221026133449336

1
2
var a="Helloe"; 
console.log(a.indexOf("e",2));

image-20221026133512464

  • lastIndexof(“字符”) 与indexof用法相同但是,该方法是从后往前找
  • slice()和数组用法一致
  • split(“,”) 将字符串拆分成一个数组,拆分规则为,
1
2
3
4
var a="Hello,zf,zhm,666"; 
var result=a.split(",");
var b=result.toString();
document.write(b);

image-20221026142533755

正则表达式

正则表达式用于定义一些字符串规则,计算机可以根据正则表达式来检查一个字符串是否符合规则,获取将字符串中符合规则的内容提取出来

正则表达式对象中有方法用于判断字符串是否符合正则表达式 test(字符串)

var a=new RegExp(“正则表达式”,”匹配模式”);

字符串第二个参数匹配模式中有两个参数可供选择 i : 忽略大小写 g 全局匹配模式

1
2
3
var reg=new RegExp("a");
var a ="a";
console.log(reg.test(a));

image-20221026164953994

若字符串符合正则表达式则返回true 若不符合则返回false

1
2
3
var reg=new RegExp("a","i");
var a ="Abcbc";
console.log(reg.test(a));

image-20221026165458188

1
2
3
var reg=new RegExp("a");
var a ="Abcbc";
console.log(reg.test(a));

image-20221026165533570

正则表达式的写法

  • 或 /a|b/ 字符串中是否有a或者b,

  • [ ]中的内容也是或的关系[ab] ==a|b , [a-z] 任意小写字母 ,[A-Z]任意大写字母

  • [^ ]是除了 ….

  • 邮箱的正则表达式

  • ```js
    var reg=new RegExp(“^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$”);
    var a =”1575443749@qq.com“;
    console.log(reg.test(a));

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

    ![image-20221026170951325](https://img.hasdsd.cn/imgimage-20221026170951325.png)

    ## DOM

    什么是DOM: DOM (Document Object Model) 文档对象模型

    - 文档:就是指整个HTML网页文档
    - 对象:将网页的每一个部分都转成一个对象
    - 模型:使用模型来表示对象之间的关系,这样方便我们获取对象

    HTML模型

    ![image-20221026171608218](https://img.hasdsd.cn/imgimage-20221026171608218.png)

    #### 节点

    Node——构成文档中最基本的单元,常用的节点分为四类:

    - 文档节点:整个HTML文档

    - 元素节点:HTML文档中的HTML标签

    - 属性节点:元素中的属性

    - 文本节点 :HTML标签中的文本内容

    以一个HTML 标签为例:

    ```html
    <a href="www.baidu.com">百度</a>

其中上面的整个HTML语句就为一个元素节点

属性href为属性节点

百度为文本节点

节点属性

image-20221026180736315

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

DOM初体验

1
2
3
4
5
6
7
8
<button id="btn"> 我是一个按钮</button>  
<script type="text/javascript">
//获取btn对象
var button=document.getElementById("btn");
//修改按钮的文字
button.innerHTML="我去DOM原来是做这个的";
console.log(button);
</script>

image-20221026182059081

事件

  • 事件就是文档或浏览器窗口中发生的一些特定交互瞬间
  • JavaScript与HTML之间的交互是通过事件来实现的
  • 对于Web应用来说,下面这些代表性的事件:点击某个元素、将鼠标移动至某个元素上方、按下键盘上的某个键

如何处理事件:我们需要通过在事件对应的属性中设置JS代码,这样的当事件被触发时这些代码将会执行

例如

1
2
3
4
5
6
7
8
9
10
11
12
<button id="btn" onclick="alert('行嗷,你真是领悟到了精髓');"> 我是一个按钮</button>  
<script type="text/javascript">
/*
浏览器已经为我们提供了节点对象,这个对象时window属性
可以在页面中直接使用,文档节点代表的是整个网页
*/
//获取btn对象
var button=document.getElementById("btn");
//修改按钮的文字
button.innerHTML="我去DOM原来是做这个的";
console.log(button);
</script>

image-20221026182857143

上述代码将JS代码写入了HTML标签中导致结构和行为耦合,不方便维护,所以我们并不推荐

我们如何去用合适JS的方法响应一个事件:

可以为节点对象对应的事件绑定处理函数的形式来响应事件,这样的话当事件被触发时,其对应的函数就会被调用

1
2
3
4
5
6
7
8
9
<button id="btn"> 我是一个按钮</button>  
<script type="text/javascript">
//获取按钮对象
var btn=document.getElementById("btn");
//绑定一单击事件
btn.onclick= function(){
alert("嗷,原来这就是事件所触发的函数啊");
}
</script>

image-20221026203028436

该事件为单击响应事件,该函数叫响应函数

页面文档加载

由于页面代码的执行顺序,我们所编写的JS代码要在页面代码以下,在整个页面代码加载完成后再执行JS代码

倘若真要把JS代码写到HTML代码之前,还能完成对应的JS功能,那么就可以使用window.onload方法

为window对象绑定onload事件该事件对应的响应函数将在页面加载之后完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<head>
<script type="text/javascript">
window.onload=function(){
var btn=document.getElementById("btn");
btn.onclick=function(){
alert("我代码在你之前,因为onload方法让我在页面加载之后才执行");
};
};
</script>
</head>
<title> 66 </title>
<body>
<button id="btn"> 我是一个按钮</button>
</body>

image-20221026205930846

DOM查询

获取元素节点

  • getElementById()——通过一个ID属性获取一个元素节点对象

  • getElementsByTagName()——通过一个标签获取一组元素节点对象

  • getElementsByName()——通过Name来获取一组元素节点对象

    元素节点对象中有一个方法innerHTML(),获取文本节点(实际上就是一个)字符串

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <script>
    window.onload=function(){
    //为id为btn01的按钮绑定一个单击响应函数
    var btn01=document.getElementById("btn01");
    btn01.onclick=function(){
    var bj=document.getElementById("bj");
    alert(bj.innerHTML);
    }
    var btn02=document.getElementById("btn02");
    btn02.onclick=function(){
    var list= document.getElementsByTagName("li");
    for(var i=0;i<list.length;i++){
    alert(list[i].innerHTML);
    }
    }
    }
    </script>

    若我们获取了元素节点对象,要使用元素节点对象中的属性则可以直接用对象.属性

    1
    2
    3
    4
    5
    6
    7
    var btn03=document.getElementById("btn03");
    btn03.onclick=function(){
    var inputs=document.getElementsByName("gender");
    for(var i=0;i<inputs.length;i++){
    alert(inputs[i].value);该节点对象中有属性value
    }
    }

    image-20221026231348225

image-20221026231356624

图片切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
#outer{
width: 300px;
height: 300px;
margin: 50px auto;
padding: 10px ;
background-color: yellowgreen;
text-align: center;
}
</style>
<script>
window.onload=function(){
var imgArr=["img/1.jpg","img/2.jpg","img/3.jpg","img/4.jpg"];//利用数组把图片的地址存进去
var index=0;
var info=document.getElementById("info");
var prev=document.getElementById("prev");
var next=document.getElementById("next");
var img=document.getElementsByTagName("img")[0];
info.innerHTML="一共"+imgArr.length+"张图片,当前是第"+(index+1)+"张";
prev.onclick=function(){
if(index>0){
index--;
img.src=imgArr[index];
info.innerHTML="一共"+imgArr.length+"张图片,当前是第"+(index+1)+"张";
}
else{
alert("这已经是第一张了");
}
}
next.onclick=function(){
if(index<imgArr.length-1){
index++;
img.src=imgArr[index];
info.innerHTML="一共"+imgArr.length+"张图片,当前是第"+(index+1)+"张";
}
else{
alert("这已经是最后一张了");
}
}
}
</script>
</head>
<body>
<div id="outer">
<p id="info"></p>
<img src="img/1.jpg" alt="原" width="300px" height="300px"/>
<button id="prev">上一张</button>
<button id="next">下一张</button>
</div>
</body>
</html>

获取元素节点的子节点

  • 通过具体的元素节点调用

    • childNodes:获取当前节点下的所有子节点
    • children:获取当前元素的所有子元素(不包括空白的文本节点)
    • firstChild:表示当前节点下的第一个子节点
    • firstElementChild:获取当前元素节点下的所有子元素
    • lastChild:表示当前节点下的最后一个子节点
    1
    2
    3
    4
    5
    6
    7
    var btn05=document.getElementById("btn05");
    btn05.onclick=function(){
    var city=document.getElementById("city");
    var cns=city.childNodes;
    alert(cns.length);
    }
    }

    我们有个疑问,为什么命名city子节点下的文本对象就4个但是会输出9个呢?因为childNodes将所有的文本节点都给包括了,以至于标签间的换行也算上了

image-20221027130322165

获取父节点和兄弟节点

  • parentNode:表示当前节点的父节点(属性)
  • parentElement:表示当前节点的父节点元素
  • innerText:表示获取到元素的文本内容 和innerHTML类似,不过他会将HTML文件自动去除
  • previousSibling:表示当前节点的前一个兄弟节点(属性)
  • previousElementSibling:表示当前节点的前一个兄弟节点的元素
  • nextSibling:表示当前节点的后一个兄弟节点(属性)

其他DOM方法

  • document.body 获取body标签的引用
  • document.documentElement 保存HTML标签
  • document.all 等价于getElementsByTagName(“*”) 两种方法皆为获取所有元素节点
  • document.getElementByClassName();根据Class值获取一组元素节点对象
1
2
3
4
//假设我们要获取class="box1"的div元素对象我们可以这么做
//首先先获取所有div元素对象
var div=document.getElementsByTagName("div");
var box1= div.getElementsByClass("box1");

DOM对象方法

  • removeChild() 删除子节点

  • 父节点.replaceChild(node1,node2) 将node1结点替代node2结点

  • 父节点.insertBefore(node1,node2) 在指定子节点前插入新节点(父节点调用,将node1插在node2的前面)

  • document.createElement() 创建元素节点

  • document.createTextNode()创建文本节点

  • 父节点.appendChild() 向指定节点下添加子节点

一个示例,创建一个”深圳”节点,添加到#city下

首先我们先获取按钮对象,然后把绑定事件响应函数,函数中首先创建li元素节点,然后再创建深圳文本节点,再将深圳文本节点添加到li节点下,

然后再获取city元素节点,将li元素节点再放到city元素节点下

1
2
3
4
5
6
7
8
var btn01=document.getElementById("btn01");
btn01.onclick=function(){
var city=document.getElementById("city");
var li=document.createElement("li");
var gzText=document.createTextNode("深圳");
li.appendChild(gzText);
city.appendChild(li);
}

点击前

点击后

image-20221028173236081

window有一个方法 comfirm,和alert类似,confirm也会弹出弹框,但 是比alert多一个取消,并且确认和取消的对应着方法的返回值为false还是true

操作样式

操作内联样式:

语法 :元素.style.样式=。。。。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>123</title>
<style>
#box1{
width: 200px;
height: 200px;
background-color: red;
}
</style>
<script type="text/javascript">
window.onload=function (){
var box1 = document.getElementById("box1");
var btn01=document.getElementById("btn01");
btn01.onclick=function (){
alert("点你咋滴");
box1.style.width="300px";
box1.style.height="300px";
box1.style.backgroundColor="blue";
}
}
</script>
</head>
<body>
<button id="btn01"> 点我一下!</button>
<div id="box1"></div>
</body>
</html>

image-20221029135943927

image-20221029135955873

通过元素.style.样式名的方法得到的是内联样式,而样式表中的无法获取,修改也是如此

获取样式表里的样式

语法:GetComputedStyle(要获取的元素,null) 该方法返回一个对象,对象中封装了该元素对应的样式,可以通过对象.样式名来读取样式

1
2
3
4
5
btn02.onclick=function (){
alert("看啥呢");
let computedStyle = getComputedStyle(box1,null);
alert(computedStyle.width);
}
  • clientWidth 返回可见宽度(属性不带px,可以直接进行计算,获取的高度和宽度包括了)
  • clientHeight 返回可见高度
  • offsetWidth:返回元素高度(包括内容区,内边距和边框)
  • offsetHeight:返回元素宽度
  • offsetParent:可以用来获取当前定位父元素,会获取到当前元素最近的开启了定位的祖先元素
  • offsetLeft:当前元素对于其定位父元素的水平偏移量
  • offsetTop:当前元素与其定位的父元素的垂直偏移量
  • scrollHeight :可以获取滚动区域的高度
  • scrollWidth:获取滚动区域的宽度
  • scrollLeft: 获取水平滚动条滚动的距离
  • scrollTop:获取垂直滚动条滚动的距离
1
2
3
4
5
6
7
8
9
10
11
12
 #box1{
width: 200px;
height: 200px;
background-color: red;
padding: 10px;
}
btn02.onclick=function (){
alert("看啥呢");
let computedStyle = getComputedStyle(box1,null);
alert(computedStyle.width);
alert(box1.clientWidth);
}

image-20221029150809057

image-20221029150817454

1
2
3
4
5
6
7
8
<div id="box3" style="position: relative">
<div id="box2" style="position: relative">

<div id="box1" style="position: relative">

</div>
</div>
</div>
1
2
3
btn02.onclick = function () {
alert(box1.offsetParent.id);
}

输出结果为

image-20221029154647426

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="box4">
<div id="box5"></div>
</div>
#box4{
width: 200px;
height: 300px;
background-color: #bbffaa;
overflow: hidden;
}
#box5{
width: 450px;
height: 600px;
background-color: yellow;
}
btn02.onclick = function () {
alert(box4.scrollHeight);
}

由于box5在box4中但box4的元素区域没有box5大所以会出现box5以滚轮的形式填满box4,而scrollHeight正式显示其中的滚轮区域高度,scrollWidth正是显示其中滚轮区域的宽度

image-20221029162951804

1
2
3
btn02.onclick = function () {
alert(box4.scrollLeft);
}

image-20221029163306987image-20221029163323506

事件对象

  • 当事件的响应函数触发时,浏览器每次都会将一个事件的一个事件对象作为实参传递进响应函数

在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标和键盘中那个键被按到,鼠标滚轮滚动的方向

例如:我们用一个区域去代表鼠标指针的位置,该区域随着鼠标的移动而移动

1
2
3
4
5
6
7
8
9
10
11
<script>
window.onload=function (){
let box1 = document.getElementById("box1");
document.onmousemove=function (ev){
let x = ev.clientX;
let y = ev.clientY;
box1.style.left=x+"px";
box1.style.top=y+"px";
}
}
</script>

image-20221030133220913

但是随后我们发现了一个问题,当鼠标移动到滚轮滚轮下的时候鼠标的位置并不在该区域的左上角了,并且随着滚轮的变化,偏移量也跟着滚轮距离顶端的偏移量所增加,我们要改正这个问题首先要知道client的所代表的区域是所示区域,而网页的原本大小要大于所示区域,滚轮以下的偏移量并不记录在clientX 或clintY 中,但我们给div区域所定位的方式为绝对位置,这就导致上述的问题

我们可以将clinetX,clinetY改为相对于整个页面的pageX和pageY这样就不会有上述问题了

JS也可以对鼠标的移动事件进行操控例如方法

对象.onmousemove 表示鼠标在该对象区域内移动这一事件

1
2
3
4
5
6
7
8
9
10
11
12
13
 <div id="areaDiv"></div>
<br/>
<div id="showMsg"></div>
<script>
window.onload=function (){
var areaDiv = document.getElementById("areaDiv");
var showMsg = document.getElementById("showMsg");
areaDiv.onmousemove=function (){
alert("牛逼不,我动了");
}

}
</script>

image-20221030125914842

事件冒泡

所谓的事件冒泡就是事件的向上传导,当后代元素上的事件被触发时,其祖代元素的相同事件事件也会被触发,在开发中冒泡是是有益的,如果不希望事件冒泡的发生可以通过事件对象来取消冒泡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
window.onload=function (){
var body = document.getElementById("body");
let box1 = document.getElementById("box1");
let span1 = document.getElementById("s1");
body.onclick=function (ev){
alert("我是body的响应函数");
}
box1.onclick=function (ev){
alert("我是div响应函数");
}
span1.onclick=function (ev){
alert("我是span响应函数");
}

}
</script>

当我们点击span区域时会出现

image-20221030141731505image-20221030141742259image-20221030141751978

这样的三个对话框,触发了span1、box1、body三个对象的onclick事件

若我们要取消冒泡则可以通过事件对象中的方法

1
2
3
4
5
6
7
8
9
10
11
12
body.onclick=function (ev){
alert("我是body的响应函数");
ev.cancelBubble=false;
}
box1.onclick=function (ev){
alert("我是div响应函数");
ev.cancelBubble=true;
}
span1.onclick=function (ev){
alert("我是span响应函数");
ev.cancelBubble=true;
}

这时box1,span1就不会出现事件的冒泡了

事件委派

将时间统一绑定给元素的共同祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件

事件的委派利用了冒泡,委派可以减少事件绑定的次数提高程序的性能,在事件对象中有一个属性target,target可直接得到触发此次事件的元素是谁

当我们想增添一个超链接并对此进行单击响应函数时,我们会遇到一个问题,新增的超链接并不拥有一开始绑定的超链接单击响应函数,这时候我们就需要事件的委派了,倘若我们一个一个的给新增的超链接再增添新响应函数,那么从性能和代码复杂度上来讲非常不乐观,我们可以通过事件的委派处理此类问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 <script>
window.onload=function (){
var ul1=document.getElementById("ul1");
var btn01 = document.getElementById("btn01");
btn01.onclick=function (){
var li=document.createElement("li");
li.innerHTML="<a href='javascript:;' class='link'>新建超链接</a>"
ul1.appendChild(li);
}
//为每一个超链接都绑定一个单击响应函数
ul1.onclick=function (ev){
if(ev.target.className=="link"){
alert("123");
}
}
}
</script>
<body>
<button id="btn01">添加超链接</button>
<ul id="ul1">
<li><a href="javascript:;" class="link">超链接1</a> </li>
<li><a href="javascript:;"class="link">超链接2</a></li>
<li><a href="javascript:;" class="link">超链接3</a></li>
</ul>
</body>

我们去分析以下这个无序列表的结构,每一个超链接都在无序列表行中,每一个无序列表行都在无需列表中,此时我们点击超链接,事件由超链接触发冒泡到无序列表行而无序列表行,进一步冒泡到无序列表中,事件随即产生,但是我们同时又发现一个问题,在ul中所有区域都可以触发ul的单击响应函数,那么怎么才能杜绝此类问题呢,就用到了事件对象中的一个属性target,我们通过target指定的对象来判断是否是超链接,进一步判断是否需要对该事件的发生进行响应

image-20221030155323532

事件的绑定

使用直接的事件绑定,一个元素的相同事件最多能绑定一个响应函数,若我们需要绑定多个函数则需要:

使用addEventListner(“XXX”,funcation(),true/boolen),三个参数分别表示为: 所要监听的动作 “不带on”, 事件的响应函数,是否在捕获阶段触发事件

可同时为一个元素的相同事件绑定多个响应函数,当事件触发时,响应函数会按照,函数的绑定顺序去执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script>
window.onload=function (){
var ul1=document.getElementById("ul1");
var btn01 = document.getElementById("btn01");
btn01.onclick=function (){
var li=document.createElement("li");
li.innerHTML="<a href='javascript:;' class='link'>新建超链接</a>"
ul1.appendChild(li);
}
//为每一个超链接都绑定一个单击响应函数
ul1.addEventListener("click",function (ev){
if(ev.target.className=="link"){
alert(123);
}
},false);
ul1.addEventListener("click",function (ev){
if(ev.target.className=="link"){
alert(456);
}
},false);
}
</script>

image-20221030161817440image-20221030161823519

拖拽

  • onmousedown 鼠标指针按住选中
  • onmousemove 鼠标指针移动
  • onmouseup 鼠标抬起取消选中
  • 事件对象.wheelDelta 获取鼠标滚轮移动的方向(向上为正,向下为负)
  • onmousewheel 滚轮事件

倘若使用的addEventListener绑定的事件,那么结束该事件的时候不能直接用return false ,而是要用 事件对象.preventDefault();取消默认行为

键盘的事件

  • onkeyDown 按键被按下
  • onkeyUP 按键被松开

键盘事件一般会绑定一些可以获取焦点对象,例如: image-20221031155258301,或者document

1
2
3
4
5
<script>
document.onkeydown=function (){
alert("按键盘了");
}
</script>

image-20221031155917101

BOM

浏览器对象模型,BOM可以使我们通过JS来操控浏览器

BOM对象:

  • window

    • 代表整个浏览器的窗口,同时windows也是网页的全局对象
  • Navigator

    • 代表当前浏览器的信息,通过该对象可以识别不同的浏览器
    • 由于历史原因Navigator中的大部分属性都不可以帮我们识别浏览器了
    • 不同的浏览器会有不同的userAgent
      • 火狐浏览器的userAgent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0
      • 谷歌浏览器的userAgent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36
  • Location

    • 代表当前浏览器的地址,通过Location可以获取地址栏信息,或者操作浏览器跳转对象
    • 如果直接输出Location可获取到地址栏信息(当前页面的完整路径) alert(location)
    • 如果将location的路径改为一个完整的路径,则会生成相应的历史记录
    • 方法:
      • assign() :用来跳转到其他页面,作用和直接修改location一样(可回退)
      • reload():重新加载当前页面,作用和刷新按钮一样
      • replace(“URL”):跳转到其他页面,不可回退
  • History

    • 属性:length:可以获取到当前访问链接的数量

    • 方法:

      • back(),可以用来回退到上一个页面和浏览器的返回键一样

      • <!--demo05.html-->
        <body>
            <h1>History</h1>
            <button id="btn01">点我一下</button>
        </body>
        <script type="text/javascript">
            var btn01 = document.getElementById("btn01");
            btn01.onclick=function (){
                history.back();
            }
        </script>
        
        1
        2
        3

        ```html
        <a href="demo05.html">去History2 </a><!--页面1-->
        当由页面1跳转到demo05.html时,我们对于btn01绑定的的单击响应事件为跳转回刚才所浏览的页面
      • forward 可以用来回到调用上一个使用back()的页面,和浏览器的前进按钮一样

      • go() 可以用于跳转到指定页面,需要一个整数作为参数,

        • 1:表示向前跳转一个页面
        • 2:表示向前跳转两个页面
        • -1:表示向后跳转一个页面
        • -2:表示向后跳转两个页面
    • 代表浏览器的历史记录,可以通过该对象来控制浏览器的历史记录

    • 由于隐私原因,该对象不能获取到具体的历史记录,只能操作 浏览器向前向后翻页,该操作只在当次访问时有效

  • Screen

    • 代表用户的屏幕信息,通过该对象可以获取到用户显示器的相关信息

定时器简介:

  • setInterval(): 定时调用,可以将函数每隔一段时间只醒一次,该方法的返回值是一个Number类型的对象,用于作为该定时器的唯一标识

    • 参数:回调函数,该函数每隔一段时间调用一次
    • 每次调用间隔的时间,单位毫秒
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <script type="text/javascript">
    var img1 = document.getElementById("img1");
    var imgArr=["img/1.png","img/2.jpg","img/3.jpg"];
    var index=0;
    setInterval(function (){
    if(index>2) index=0;
    img1.src=imgArr[index];
    index++;
    },1000);
    </script>
    • clearInterval(),关闭定时器,传入的参数即为该定时器的返回值
  • setTimeout():延时调用一个函数不马上执行,而是隔一段时间之后再执行,而且只会执行一次 ,该方法返回对象和setInterval()性质类似

    • 参数:回调函数,该函数在规定时间后调用一次
    • 调用函数的时间,单位毫秒
  • clearTimeout(),关闭延时器,传入的参数即为延时器所返回的对象

类的操作

我们可以通过修改元素的class属性间接的修改样式,这样一来我们可以只修改一次就修改多个样式,此时浏览器只需渲染页面一次,性能比较好,并且这种方式可以使表现和行为进一步分离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<style type="text/css">
.box1{
width: 123px;
height: 456px;
background-color: red;
}
.box2{
width: 456px;
height: 123px;
background-color: #bbffaa;
}
</style>
<div class="box1" id="b1"></div>
<button id="btn01">超级变变变</button>
<script type="text/javascript">
var b1 = document.getElementById("b1");
var btn01 = document.getElementById("btn01");
btn01.onclick=function (){
b1.className="box2";
}
</script>

image-20221102103437073image-20221102103454997

但是这样会出现问题,即便有box2样式,b1中还会持续添加box2为了杜绝这种问题我们选择用正则表达式来解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 .box1{
height: 456px;
background-color: red;
}
.box2{
width: 456px;
height: 123px;
background-color: #bbffaa;
}
<div class="box1" id="b1"></div>
<button id="btn01">超级变变变</button>
<button id="btn02">删除删除</button>
<script type="text/javascript">
var b1 = document.getElementById("b1");
var btn01 = document.getElementById("btn01");
var btn02 = document.getElementById("btn02");
function addClass(obj,cn){
if(!hasClass(obj,cn)) {
obj.className += " " + cn;
}
}
function removeClass(obj,cn){
var reg=new RegExp("\\b"+cn+"\\b");
obj.className=obj.className.replace(reg,"");
}
function hasClass(obj,cn){
var reg=new RegExp("\\b"+cn+"\\b");
return reg.test(obj.className);
}
btn01.onclick=function (){
addClass(b1,"box2");
}
btn02.onclick=function (){
removeClass(b1,"box2");
}
</script>

函数的prototype

  1. 函数的Prototype属性

    • 每个函数都有prototype属性,他默认指向一个Object空对象(原型对象),每个圆形对象中都有一个属性constructor,他指向函数对象
  2. 给原型对象增加属性(一般都是方法)

    • 作用:函数的所有实例对象自动拥有原型中的属性(方法)

    • 每一个函数function都有一个prototype即为显示原型(属性)

    • 每一个实例对象都有一个“—proto——可成为隐式原型(属性)