JavaScript(入门)

一、JavaScript基本概念和作用

  1. 概念:JavaScript(简称“JS”) 是一种具有函数优先的轻量级,解释型的脚本语言。与HTML和CSS合称”前端三剑客“。

  2. 组成:ESMA Script + BOM + DOM

    • ESMA Script:主要是由ESMA(欧洲计算机制造商协会)制定的JS标准,即:JS的基础语法
    • BOM:BOM(浏览器对象模型)是用于描述这种对象与对象之间层次关系的模型。BOM由多个对象组成,其中代表浏览器窗口的Window对象是BOM的顶层对象,其他对象都是该对象的子对象。主要用于获取浏览器信息或操作浏览器
    • DOM:DOM(文档对象模型)是W3C组织推荐的处理可扩展置标语言的标准编程接口。主要用于操作网页中的元素
  3. 特点

    • 基于对象。JavaScript是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象
    • 动态性。JavaScript是一种采用事件驱动的脚本语言,它不需要经过Web服务器就可以对用户的输入做出响应。在访问一个网页时,鼠标在网页中进行鼠标点击或上下移、窗口移动等操作JavaScript都可直接对这些事件给出相应的响应
    • 交互性。JavaScript由于其动态性,让他具有良好的交互性,这也是它能被广泛应用于各大浏览器的原因之一
    • 简单易学。JavaScript是一种弱类型语言,对使用的数据类型未做出严格的要求,是基于Java基本语句和控制的脚本语言,其设计简单紧凑
    • 跨平台性。JavaScript运行不依赖于操作系统,同时它不需要服务器的支持,仅需要用户的浏览器支持,不同于服务端脚本语言,它是一种客户端脚本语言(相较而言,服务端脚本语言的安全性高于客户端脚本语言),而当今大部分浏览器都支持它
  4. 作用

    • 嵌入动态文本于HTML页面。实现网页特效,包含广告代码、导航菜单代码、日历控件、飘浮特效、文字特效、色彩特效及图片特效等
    • 让网页和用户实现交互。对浏览器事件做出响应,比如实现弹出窗口、元素的移动、窗口数据传递等
    • 在数据被提交到服务器之前验证数据。比如通过JS正则表达式验证表单中某数据域的数据类型或应满足的规则等
    • 基于Node.js技术进行服务器端编程。比如编写微信小程序
  5. JavaScript发展史:点击这里查看

    ES各版本发布时间:(注意ES版本不等于JS版本)

    • ES1:1997
    • ES2:1998
    • ES3:1999
    • ES4:ESMA预计在2008发布,但因兼容性成本太高,遭各大浏览器厂商抵制,未能如愿发布,详情
    • ES5:2009
    • ES5.1:2011
    • ES6:2015
    • ES7:2016
    • ES8:2017
    • ES9:2018
    • ES10:2019
    • ES11:2020
    • ES12:2021
  6. 学习平台菜鸟教程

  7. 前端小Demo:👉这里



二、JavaScript的引入方式

JavaScript的引入方式可以类比CSS的引入方式,共有三种:内联样式引入、内部样式引入、外部样式引入

这些样式的优先级:内联样式>内部样式||外部样式 后面两个的优先级遵循就近原则

  • 内联样式引入:(也称标签级引入方式)直接在HTML标记属性值中直接写入JavaScript代码

    <!DOCTYPE html>
    <html lang="zn">
    <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>引入方式测试1</title>
    </head>
    
    <body>
        <button type="button" onclick="alert('Hello World!')"> 点我!</button>
        <!--
    onclick是点击事件,点击就执行""中的内容,alert是应该弹窗。综合就是点击"点我!"这个按钮就弹出一个有"Hello World!"的弹窗
       -->
    </body>
    
    </html>
    

    image-20220412154100387

  • 内部样式引入:(也称页面级引入方式)使用script标签进行引入Javascript代码

    <!DOCTYPE html>
    <html lang="zn">
    
    <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>引入方式测试2</title>
        <script>
            <!--
            function hello() {
                console.log("Hello World");//浏览器控制台输出
            }
            -->
            /*
            注意当浏览器能够识别script标签时,script中的<!---->不会被识别;
            当浏览器不能识别script标签时
            ,<!---->会被识别, 因为所有的浏览器都能识别HTML的标签,
            但是不是所有的浏览器都能识别js代码,
            这样写的目的是防止js代码在不能识别js的浏览         
            器上报错。目的是提高容错(又学到一个小技巧)
            */
        </script>
    </head>
        
    <body>
        <script>hello();</script>
    </body>
    
    </html>
    

    image-20220412152035585

  • 外部样式引入:(也称项目级引入方式)将JS代码写在js文件中,html代码中使用script标签引入 (常用)

    //js文件中的代码:
    function hello() {
        document.write("Hello World!");//网页输出
    }
    
    <!--html文件中的代码-->
    <!DOCTYPE html>
    <html lang="zn">
    
    <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>引入方式测试3</title>
        <script src="js代码部分.js"></script>
        <!--注意script必须成对出现,不可写成<script/>-->
    </head>
    
    <body>
        <script>
            hello();
        </script>
    </body>
    
    </html>
    

    image-20220414135553684



三、JavaScript基础语法

1、变量

变量可分为:局部变量全局变量

  1. 变量的命名规则

    变量名可以由数字0~9、字母A~Z或a~z、下划线 “_” 或美元符 “$”组成,但是不能以数字开始
    例如:1a、d-c 都是非法的变量名
         _1a、$bs、d_as、_、$ 都是合法变量名
    

    • 不能使用JavaScript中的关键字保留字作为变量名。在JavaScript中定义了50多个关键字或保留字,它们是JavaScript内部使用的,不能作为变量的名称。如var、int、double、true等都不能作为变量的名称
    • JavaScript的变量名区分大小写,如:str和Str分别代表两个不同的变量。最好进行 驼峰式命名,常量用大写字母
    • JavaScript的变量名最好能够说明其代表的意思,譬如:定义两个字符串变量可用str1和str2,求和变量可用sum等
  2. 变量的声明

    变量可以用var、let、const三种方式来定义,变量不需要指定某一种数据类型,被赋值后自动确定为相应的数据类型

    var 变量名 =; //变量都是使用var关键字来声明
    //例如:
    var a = 123;
    
    'use strict';//进入严格模式,可以防止一些不严谨而出现的bug(严格模式中变量的定义不能使用var来定义)
    

    反正使用Java的规则取命名和声明肯定不会错

    注:JavaScript是一种弱类型语言可以不进行声明直接使用,例如:a=123。不使用var声明时,浏览器在解析JavaScript代码时会将其解释为全局变量。在ES6中规定用let关键字来定义局部变量。

    var和let的区别:(参考***

    • let是块状作用域,而var是函数作用域(var定义的变量,内部函数可以访问外部函数的,反之不成立;而let定义的变量只能在一个{}代码块中有效,作用域为声明位置到该代码块结束位置)
    • let不能在定义之前访问该变量,而var可以(因为var定义的变量会被预解析,输出的是undefined,而let就直接报错)
    • let不允许变量在同一个作用域被重新定义,var允许

    let 和 const很相似,作用域相同,都是块状作用域、不能重复定义、不能在定义之前访问该变量,它们主要的区别是const定义的变量不允许被重新赋值,而let允许,通常用const去定义常量

    所有的全局变量都绑定在window对象上,可以通过window.变量名来访问全局变量。


2、数据类型

js中的数据类型可分为两大类:基本数据类型(7种) 和 引用数据类型(……种)

2.1 基本数据类型

基本数据类型共7种:Number、Boolean、String、Null、Undefined、Symbol、BigInt。其中前五种也叫作原始数据类型,是直接存储在中的简单数据段,占据空间小、大小固定,属于被频繁使用的数据。引用数据类型存储在堆内存中,占据空间大、大小不固定。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体。

Number和BigInt范围的区别:

Number的范围:-9007199254740991 (-(2^53-1) ~ 9007199254740991(2^53-1) )

[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER]

BigInt的范围:5e-324 ~ 1.7976931348623157e+308

2.1.1 Number
  • Number(数值型):表示所有类型的数值(js种把 整型和浮点型 都归为数值型)

    //Number类型举例:
    var a=123; //整数123
    var b=1.23;//浮点数1.23
    var c=1.2e3;//科学计数法1.2*10^3
    NaN //非数字
    Infinity //超出Number的最大表示范围,表示无穷大
    

    拓展:

    NaN

    • NaN虽然表示是一个非数字 , 但是一般是算术运算执行的结果, 因此NaN 仍然是 数值类型
    • 含NaN执行运算时 :如果是非加法运算,执行结果都是NaN;如果是加法运算 且 都是数值型的,结果为NaN,含有字符串型的,对数据进行拼接
    • NaN 永远不会等于NaN。 NaN == NaN 执行结果是 false
    • 只能通过isNaN( )来判断一个数是否为NaN

    Infinity:JavaScript中数值的范围:5e-324 ~ 1.7976931348623157e+308

    • 超过5e-324 的是负数的就是 -0,正数的就是 0。例如:-5e-325=-0,5e325=0
    • 超过1.7976931348623157e+308的是负数的就是-Infinity,是正数的就是Infinity。2e+308=Infinity,-2e308=-Infinity
2.1.2 Boolean
  • Boolean(布尔型):true、false
2.1.3 String
  • String(字符串型): 表示字符串或单给字符(将Java中的String和char类型合并了)

    //可以使用  '字符串' 或 “字符串”  或 `字符串` 包裹,特殊字符用转义字符表示
    var str1 = "hi!";
    var str2 = "ghp";
    var str3 = `${str1}${str2}`;//EL表达式,必须在``中使用
    alert(str3);//弹出hi!ghp
    
    //字符串的常见操作
    var str = "study";
    //1.输出字符串的长度
    alert(str.length());
    //2.输出字符串的第1个字符(Java不能这样输出,Java只能输出字符串数组的某一个字符)
    alert(str[0]);//注:不能单独使用str[]去改变字符串中的一个值
    //3.字母大小写转换
    str.toUpperCase();
    str.toLowerCase();
    //4.输出需要寻找字符第一次出现的索引位置
    alert(str.indexOf('t'));//如果未找到返回-1
    //5.输出字符串中[a,b)之间的字符串
    alert(str.substring(1,3));//输出tu
    
    
2.1.4 Null
  • Null(空):表示一个空对象。当对象不存在时,输出时会返回NUll
2.1.5 Undefined
  • Undefined(未定义型):表示变量不含有任何值

    常见返回是undefined的情况:

    • 变量是未定义(未声明)的状态

    • 变量没有进行手动赋值,编译器会默认赋值undefined(和Java不同,Java会给未赋值的变量自动赋相应初值)

    • 获取对象中不存在的属性时默认为undefined

    • 函数需要实参,但是调用时没有传值,形参是undefined

    • 函数调用没有返回值或者return后没有数据,接受函数返回值的变量默认为undefined

    • 使用Map中的set方法时未为key添加value时,value默认为undefined

2.1.6 Symbol
  • Symbol(独一无二的值,ES6 新增):表示独一无二的值。Symbol 值通过 Symbol() 函数生成,其中Symbol()函数可以接收字符串参数,表示对 Symbol 实例的描述

    好文!值得推荐 => 点这里1 点这里2

2.1.7 BigInt
  • BigInt (大整数,能够表示超过 Number 类型大小限制的整数,ES11新增):可以用来更安全的表示Number范围外的数

    拓展:

    • BigInt 类型不能用 Math 对象中的方法

    • 不能和 Number 示例混合运。因为 JavaScript 在处理不同类型的运算时,会把他们先转换为同一类型,而 BigInt 类型变量在被隐式转换为 Number 类型时,可能会丢失精度,或者直接报错

    • BIgInt和Number能直接使用 “==”、“<”、“>” 进行比较


2.2 引用数据类型

Object(对象:是拥有属性和方法的数据) :在JavaScript中,除了基本数据类型其他的都是引用数据类型,相应的每种引用数据类型都有其相应的对象JS中一切皆为对象,常见的有:Array、Function、Window、Documen、Date、RegExp……

  • 对象的定义:

    var person = {
        name : "ghp",
        age : 19,
        eamail : "12345678@qq.com"
    }
    var a = new person;//构造器创建对象
    

JavaScript中对象按定义可以分为:预定义对象和自定义对象。预定义对象是指系统提供的已经定义好的,可直接使用的对象,包含内置对象、文档对象和浏览器对象。按是否实例化可分为:实例化对象和普通对象。实例化对象,和Java中概念相同,抽象的类的对象不能被实例化。其实实例化有两个目的:一是为类创建了一个对象方便改变类中的属性值,二是一旦实例化,系统就会为该对象创建一个存储区域,该区域用来放你该对象属性

  • 对象的操作:(和Java类似)

    //1.对象的引用:(根Java类似)
    var a = person.name;//将对象person的name属性值赋给变量
    //2.删减已有属性:delete 对象名.属性名;
    delete person.name;
    //3.添加新属性:对象名.属性名 = 属性值;
    person.sex = "男";
    //4.判断属性是否在对对象中:属性值 in 对象名;(还可以用来判断对象父类中的属性)
    console.log("toString" in person);//输出true,toString是person的一个父类中的属性
    //5.判断一个属性是否是这个对象自身拥有的:对象名.hasOwnProperty();
    console.log(person.hasOwnProperty("toString"));//输出false
    //6.判断一个对象是否为另一个类的实例(还可以用于判断是否为另一个类的子类):对象名 instanceof 类名
    var a = new Array();
    console.log(a instanceof Array);  //输出true
    console.log(a instanceof Object); 
    /*输出true,Array是Object的子类(Object是所有对象的父类,也叫原型,在第四章会讲到)*/
    console.log(a instanceof Function); //输出false
    //7.操作当前对象的属性和方法:this(java中是无法控制this的指向的,但是JS中可以通过apply控制this指向)
    var Person = {
        name : "ghp",
        birth : 2002,
        age : getAge
    }
    1)当以普通函数的形式调用,this指向window对象
    var getAge = fun(){
        var now = new Date().getFullYear();//获取当前的年号
        return this.age = now-this.birth;
    };
    getAge();//this指向window,输出:NaN
    getAge.apply(Person,[])//输出:20。this指向Person,传入函数的参数为空
    2)当以构造函数的形式调用,this指向新创建的对象
    var a = new f(){
        this.age = age;
    };//this指向a
    3)当以方法的形式调用,this就指向当前调用的对象
    console.log(Person.age);//this指向Person对象,输出:20
    //8.批量操作指定对象的所有属性和方法:with(对象名)
    with(person){
        var str = "姓名:" + name;
        var str = "年龄:" + age;
        var str = "性别:" + sex;
    }
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8woZnYuR-1652429513683)(D:/用户/ghp/Pictures/Typora/image-20220510193851371.png)]


2.2.1 Array
  • Array(数组):是预定义对象中的内置对象。用于在单个变量中存储多个值。(一给数组可以用来存多种类型的数据并且数组长度可变,和Java不同)

    //数组的常规操作
    var arr[1,2,3,4,5,6];
    //1.可以使用arr[]改变索引处的字符
    arr[2]=7;//将3改变成7,字符串.[]不能
    //2. 可以使用arr.length改变数组长度(Java中不能改变数组长度,在Java中数组一经定义长度就确定了)
    arr.length=2;//数组中第2个值以后的值都丢失,数组长度变为2
    arr.length=8;//数组的第7,第8个为undefined
    //3.输出需要寻找字符第一次出现的索引位置,未找到返回-1
    console.log(arr.indexOf());//字符串的“1”和数字1不同
    //4.截取数组的一部分,和操作字符串的substring()相似
    console.log(arr.slice(1,3));//输出[2,3]
    //5.push、pop
    arr.push("7",8);//将"7"、8加入到arr的尾部,数组长度增加2,此时arr=[1,2,3,4,5,6,"7",8]
    alert(arr.pop());//输出arr最后一个元素,数组长度减1,此时arr=[1,2,3,4,5]
    //6.unshift(与push作用相反,添加元素在头部,数组长度增加)、shift(与pop作用相反,弹出头部的第一个元素,数组长度减1)
    //7.对数组进行排序:arr.sort(),根据Unicode编码的字符大小来排序
    //8.将数组中的元素反转:arr.reverse(),此时arr=[6,5,4,3,2,1]
    //9.输出一个新数组,但是不改变原数组
    console.log(arr.concat(7,"8"));//输出:[1,2,3,4,5,6,7,"8"],此时arr不变
    //10.输出链接字符串,不改变元素组
    console.log(arr.join("-"));//输出:1-2-3-4-5-6
    //多维数组的定义:
    var arrs[[1,2],[],[]];
    
2.2.2 Function
  • Function(函数):既有预定义对象,又有自定义对象。是由事件驱动的或者当它被调用时执行的可重复使用的代码块

    和Java中的“函数”有很大区别,严格来讲Java中是没有“函数”这个概念的,Java中函数是必须写在类中的,是类的一个成员,需要类创建对象然后通过创建的对象来引用类中的方法(或者说直接在该函数同一个类中使用函数名来引用),它不属于一种数据类型,是属于类中的成员(或属性)。而在JS中是有函数这个概念的,函数可以自己创建对象来被调用,同时它属于引用数据类型。

    Java中函数和JS中“函数”的比较:

    • Java中没有“函数概念”,只有“方法“概念。JS中函数和方法概念都有,JS中函数可以有相应的对象,可以直接调用也可以通过对象调用, 但是方法不能直接调用, 只能通过对象来调用,方法是一种特殊形式的函数(写在对象中或被对象属性调用的函数);
    • Java中“方法”有重写和重载。JS中“函数”不能重载但能重写;
    • Java中”方法“有分为普通方法和构造方法。JS中”函数“也分为普通函数和构造函数;
    • java中的”方法“必须写在一个类中,是类的一个部分,通过类或类的实例化对象来调用。JS中”函数“是一种数据类型,可以单独写在外面,通过函数名调用或函数的实例化对象来调用;
    • Java中”方法“的参数是强类型的,必须要传指定的数据类型、指定个数的数据。JS中函数的参数是弱类型参数,可以传任意个参数,也可以不传参数(参数默认为undefined),也可以传任意类型的参数。
    • 函数的定义:

      //1.标准定义
      function f([形参1],[形参2],……){
          ……;
          return 数据;//需要返回值就写
      }
      //2.匿名定义
      var f = function ([形参1],[形参2],……){//和方法1等价
          ……;
          return 数据;//需要返回值就写
      }
      f();//无返回值函数的调用6
      var a = f();//有返回值函数的调用
      //构造函数的定义:
      var Person = function(name, age, gender) {
          this.age = age;
          this.name = name;
          this.gender = gender;
      }
       var p = new Person("ghp", 20, "男");
      

      构造函数和普通函数的定义是差不多的,只是习惯上我们会将构造函数的函数名首字母大写。主要区别是调用方式不同,普通函数是直接调用,而构造函数必须使用new关键值创建新对象,通过对象来调用

    • 解决传参问题:(函数的参数除了是基本数据类型和引用数据类型,还可以是HTML中的元素)

      //手动抛出异常来判断传入的参数是否是指定数据类型
      var abs = function(a) {
          if (typeof a !== "number") {
              throw "not a Number";
          }
          if (a > 0) {
              return a;
          } else {
              return -a;
          }
      }
      //操作多余的参数:arguments(本质是用一个数组来接收所有参数)
      var f = function(a) {//假设调用f时多传了b、c两个参数
          for(var i=0;i<arguments.length;i++){//遍历所有传进来的参数
              console.log("第"+i+"参数:"+arguments[i]);
          }
      }
      //获取除了已定义的参数外的其他参数:...rest
      var f = function(a,...rest){//假设调用f时多传了2、3两个参数
          console.log("已定义的参数:"+a);
          console.log("未定义的参数:"+rest);//输出:未定义的参数:2,3
      }
      
    • 函数中变量的作用域及其定义规范:

      • 内部函数可以访问外部函数的成员,反之不成立

      • 使用变量时,有一个由内而外的查找过程,当内部函数和外部函数变量重名时,内部函数会屏蔽外部函数的变量

      • var定义的变量作用域为函数式作用域,只要在函数内部(非内部函数)定义就能访问,但要访问变量的所赋的值需要先定义后使用,否则为undefined;let定义的变量作用域为块状域,一定要先声明后使用否则会报错。所以一定要在函数的头部定义变量

      • JS中只有一个全局作用域,任何函数中的变量,假定没有在其函数的作用范围中找到,就会向外查找如果在全局变量中都没有找到,就会报错Reference Error

      • 由于所有的局部变量都会绑定在window对象上,在使用过程中很容易产生冲突。解决方法:自定义一个全局变量空间,将全局变量绑定在自定义的全局变量空间上

        var SPACE = {};//写在文档的最开始位置
        SPACE.PI = 3.1415926;//定义一个全局变量PI
        
2.2.3 Window
  • Window:是预定义对象中的浏览器对象,代表当前的浏览器窗口(一个浏览器可以有多个窗口,代表浏览器可以用多个Window对象),是其他所有浏览器对象的父级,同时也是唯一一个引用不需要声明的对象

    Window对象中常用的方法

    • window.alter()
    • window.innerHerght(); //获取浏览器窗口内部高度,窗口
    • window.innerWidth();
    • window.outerHeight(); //获取整个浏览器窗口的高度
    • window.outerWidth();

    在这里插入图片描述

    • window.screen.width(); //屏幕的宽、高
    • window.screen.width();
    • location.assign(‘url’); //实现网页跳转

    Window对象中常用对话提示框方法

    • Open(URL,window name, window features):打开新窗口。

    • Close():关闭一个浏览器窗口。

    • alert(message):弹出一个警示对话框。

    • prompt(message,defaultmessage):弹出一个提示对话框。

    • confirm(message):弹出一个确认对话框。

    • setTimeout(expression,time):设置一定时间后自动执行一次expression代表的代码,使用time设置时间,以毫秒为单位。

    • setInterval(expression,time,[args]):设置一个时间间隔,使expression代表的代码可以周期性地被执行。使用time设置时间,以毫秒为单位。


    备注

    prompt()方法不但可以像alert()方法和confirm()方法一样显示信息,而且还提供一个文本框要求用户从键盘输入自己的信息,同时它还包括“确定”和“取消”按钮。

    其基本语法格式:prompt(“提示信息1”,“提示信息2”);

2.2.4 Document
  • Document:document对象是浏览器对象,代表浏览器窗口中的文档,可以用来处理、访问文档中包含的HTML元素,如各种图像、超链接等。

    write()方法,是document对象的最常用方法,他会自动解析HTML标签

    document.write('<h1>待添加的文字<h1>');  //会在网页上输出h1标题类型的文字
    

    document对象的属性有:

    • title:表示文档的标题。
    • bgColor:表示文档的背景色。
    • fgColor:表示文档的前景色。
    • alinkColor:表示点击时超链接的颜色。
    • linkColor:表示未访问过的超链接颜色。
    • vlinkColor:表示已访问过的超链接颜色。
    • URL:表示文档的地址。
    • lastModified:表示文档的最后修改时间。

    拓展:

     document.cookie; //获取本地信息

    一些黑客可以通过伪造cookie或者劫持cookie使用你的信息盗刷卡

    一般服务器会使用cookie:httpOnly;进行加密

    history必须要有历史记录

    • history.back(); 网页回退

      history.forward(); 网页前进

      history.go(n); //n去正数表示前进几个网页 ,负数表示后退几个页面

      <body>
          <a href="https:baidu.com">点击跳转到百度</a><br>
          <button onclick="advance()">点击前进</button>
      
          <script type="text/javascript">
              var a = document.querySelector('button');
              function advance() {
                  history.forward();
              }
          </script>
      </body>
      
2.2.5 Date
  • Date(日期):是JS中的预定义对象中的内置对象,其内部含有特有的方法,用于处理日期和时间

    • 常用操作:

      var now = new Date();
      now.getFullYear();//得到当前的年份,下面同理
      now.getMoth();//月
      now.getDate();//日
      now.getDay();//星期
      now.getHours();//小时
      now.getMinutes();//分
      now.getSeconds();//秒
      now.getTime();//时间戳,全世界统一且唯一动态变化的,起始:1970.1.1.00:00:00
      console.log(new Date(now.getTime()));
      //对时间戳进行解码,输出当前时间:Sat Apr 16 2022 23:16:56 GMT+0800 (中国标准时间)
      console.log(now.toLocaleString());//输出本地时间:2022/4/16 23:23:44
      now.toGMTString();//格林威治标准时间,输出:Sat, 16 Apr 2022 15:28:12 GMT
      

      时间戳(time-stamp)是一个经加密后形成的凭证文档,它包括三个部分:

      • 需加时间戳的文件的摘要(digest)

      • DTS收到文件的日期和时间

      • DTS的数字签名

      一般来说,时间戳产生的过程为:用户首先将需要加时间的文件用Hash编码加密形成摘要,然后将该摘要发送到DTS,DTS在加入了收到文件摘要的日期和时间信息后再对该文件加密(数字签名),然后送回用户。

      时间戳的作用:客户端在向服务端接口进行请求,如果请求信息进行了加密处理,被第三方截取到请求包,可以使用该请求包进行重复请求操作。如果服务端不进行防重放攻击,就会服务器压力增大,而使用时间戳的方式可以解决这一问题

2.2.6 …

RegExp(正则表达式)……


拓展:

  • 数据类型的判断:typeof 参靠文章 => 这里

    用法:typeof(表达式) 。eg:

    console.log(tyeof((1+2)));//输出:number
    console.log(tyeof((1+2+"a")));//输出:string
    console.log(tyeof(hello));//hello是函数名,输出:function(经测试发现匿名函数前的变量名类型是函数)
    consele.log(tyeof(person));//输出:object
    
  • JSON

    JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。(早期都是使用 XML 数据交换格式的)

    • JSON的作用:

      • 让数据的结构层次分明,简洁而清晰,易于人理解和阅读

      • 易于机器解析和生成,并能够有效地提升网络传输效率

    • JSON和JS种对象的关系:JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串

      var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
      var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
      
    • JSON和JS对象的转换:

      //将JSON字符串转换成JS对象
      var obj = JSON.parse('{"a": "Hello", "b": "World"}'); //结果是 {a: 'Hello', b: 'World'}
      //将JS对象转换成JSON字符串
      var json = JSON.stringify({a: 'Hello', b: 'World'}); //结果是 '{"a": "Hello", "b": "World"}'
      

3、符号

JavaScript中符号可以分为:运算符 和 转义字符,以及一些特殊字符。注释符和Java中一样

3.1 运算符

运算表达式=运算符+数据,实质是一个值

3.1.1 算术运算符

image-20220412172036301

”+“还可以用于字符串之间的连接,如:

var str1="123";
var str2="123";
var str3=str1+str2;//此时输出str3,会得到123123
//当一个表达式中有一个String类型,进行加法运算都会变成字符串的拼接

此外:”=“表示赋值

3.1.2 比较运算符

image-20220412172131222

除表中的以外,还有 绝对等于:“===”,表示 数据类型相同 同时 值也相同(Java中没有)

3.1.3 逻辑运算符
运算符功能描述
&&逻辑与。同为真才为真,有一个为加,结果为假
||逻辑或。同为假才为假,有一个为真,结果为假
逻辑非。真为假,假为真

此外:“!!” 表示:将数据转成所对应的Boolean类型,例如:

var a = 123;
var b = !!a;
console.log(b);//输出:true。在js中+0(0)\-0转成Boolean型都是false,其他的数值都是true
3.1.4 位运算符
运算符功能描述
&位与。同为1才为1,有一个为0,结果为0
|位或。同为0才为0,有一个为1,结果为1
^异或。不同取1,相同取0
~取反。1取0,0取1
>>右移。等价于除以2
<<左移。等价于乘以2

此外:“~~” 表示:浮点数取整。例如:

var a = 3.1415926;
var b = ~~a;//此时b=3
3.1.5 条件运算符
表达式1 ? 表达式2 : 表达式3 //当表达式1为真时,执行表达式2;为假时执行表达式3
3.2 转义字符
转义字符功能描述
\0空格(\u0000)
\b退格符(\u0008)
\t水平制表符(\u0009)
\n换行符(\u000A)
\v垂直制表符(\u000B)
\f换页符(\u000C)
\r回车符(\u000D)
\"双引号(\u0022)
\’单引号(\u0027)
\\反斜杠(\u005c)
\xHH由两位十六进制数组成数值表示latin1字符
\XXX由三位十六进制数组成的数值(000~377)表示Unicode编码
\uHHHH由四位十六进制组成的数值来表示表示Unicode编码
  • 退格符:用来删除前一个字符,对应键盘上的Backspace键

  • 水平制表符:让字符串成4的倍数输出,不足的补空格

  • 垂直制表符:让\v后面的数据换行同时接着与上面数据的末尾对齐输出 输出居然乱码了?

  • 换行符:让光标往下一行(不一定到下一行行首,但通常是首行)

  • 回车符:让光标重新回到本行开头

  • Unicode编码参考文章 => 点击查看

注意:在window操作系统中,Enter相当于 \r\n。参考文章 => 点击查看


4、流程控制

4.1 分支结构:
if(表达式)……else……
if(表达式)……else if(表达式)……else……
……无限套娃
4.2 循环结构:
//1.while循环:
while(表达式){
    ……;
}
do{
    ……;
}while(表达式);
//2.for循环:
for([let 变量赋值];判断;[表达式]){//[]中的内容可以省略
    ……;
}
for(var i in arr){//循环遍历数组时,i表示索引位置;循环遍历对象时;i表示一个属性,也能用person[i]表示和i是一样的效果
    console.log(i);//输出:0,1……
}
//3.forEach循环:用于输出一个数组的所有值或对象属性的所有值
arr.forEach(function(value){
    console.log(value);//循环输出数组arr中的值
});
//4.分支语句switch
switch (表达式){ 
    case value1: 语句块1; 
    case value2: 语句块2; 
    case value3: 语句块3;
    ... 
    default: 语句块n;
} 
//6.关键字:break、continue和Java中一样

拓展:

  • Map:给对象设置若干对相关联的键(key)和键值(value)

    var map = new Map([["a",92],["b",99],["c",95]]);//输出:Map(3) {'a' => 92, 'b' => 99, 'c' => 95}
    //1.通过key获得value
    var i = map.get("a");//输出:92
    //2.向map中增加一对新的key和value
    map.set("d",66);//输出:Map(4) {'a' => 92, 'b' => 99, 'c' => 95, 'd' => 66}
    //3.删除键,以及对应的键值
    map.delete("a");//输出:Map(2) {'b' => 99, 'c' => 95}
    
  • Set:无序不重复的集合

    var set = new Set([1,1,"1",2,3]);//set中只有一个1
    //1.向set中添加一个元素,在末尾
    set.add("ghp");//输出:Set(5) {1, '1', 2, 3, 'ghp'}
    //2.删除set中指定的一个元素
    set.delete(1);//输出:Set(3) {'1', 2, 3}
    
  • Iterator:迭代器 (ES6新增)

    //1.遍历数组
    var arr = [1,2,3];
    for(let i of arr){
        console.log(i);//输出:1 2 3。和for in 是不同的,i表示的是arr的值
    }
    //2.遍历map
    var map = new Map([["a",92],["b",99],["c",95]]);
    for(let i of arr){
        console.log(i);//输出:(2)["a",92] (2)["b",99] (2)["c",95]
    }
    

    原生具备 Iterator 接口的数据结构: (引自***

    Array、Map、Set、String、TypedArray、NodeList 对象、函数的 arguments 对象。

    对于不具备Iterator接口的数据结构(主要是对象)都需要自己在Symbol.iterator属性上面部署,这样才会被for…of循环遍历。原因:对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定。本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,就等于部署一种线性转换。



四、面向对象编程

引言:

  面向对象程序设计(Object Oriented Programming)作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征,只能对事物特征和变化规律的一种抽象,且在它所涉及的范围内更普遍、更集中、更深刻地描述客体的特征。通过建立模型而达到的抽象是人们对客体认识的深化。

1、原型

在JavaScript中有原型概念,和Java中的父类是相似的概念。原型的实现:

var Student{
    name:"qingjiang",
    age:2,
    run:function(){
        console.log(this.name+"run......");
    }
};
var xiaoming = {
    name:"xiaoming"
};
xiaoming._proto_ = Student;//小明的原型是Student函数对象,和Java中继承是类似的
xiaoming.run();//控制台输出:小明run......

2、继承

注:是在ES6引入的,使用关键字extend,和上面的原型是一样的效果,继承的本质就是原型

class Student{
	constructor(name){//constructor是定义构造器的关键字,和Java中的构造方法是一样的效果
		this.name = name;
	}
    hell(){
        alert("hello");
        
    }
}
var xiaoming = new Student("xiaoming");//实例化对象

class xiaoStudent extends Student{
    constructor(name,grade){//重写父类的方法
        super(name);//调用父类的方法
        this.grade = grade;
    }
}

😆感觉在写Java

拓展:

  原型链:每一个对象都会有一个原型对象Object,Object本身也是一个对象,它自己的原型是它本身,如此就形成了一个原型循环链

在这里插入图片描述

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。——摘自《javascript高级程序设计》


五、操作DOM对象

引言:

DOM对象就是文档对象(document)

DOM模型:整个网页就是一个DOM树,将HTML中的每个标签看作一个结点,每个结点都可以看作一个对象,它们的层次关系表示标签在网页中的嵌套关系,同一层结点的左右次序表示这些标签对象出现的先后顺序。

在这里插入图片描述

对DOM的操作,要操作先要获取一个DOM节点。(对DOM的操作预示着:可以只用JS实现一个网页)

增、删、改、查

5.1 获取DOM节点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YFeORvtU-1652429513687)(D:/用户/ghp/Pictures/Typora/image-20220510202453789.png)]

获取子节点

document.querySelector('#idname'); //获取document节点中的拥有这个id名的节点
document.querySelector('.classname'); //获取document节点的第一个节点的拥有这个class类名的节点
document.querySelector("TagName");  //获取ducument节点中第一个标签的节点
document.querySelectorAll()          //获取所有类型的节点

eg:

<!DOCTYPE html>
<html lang="zn">
<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>Test</title>
</head>
<body>
    <div id="father" class="father">
        <p id="p1" class="p1">123</p>
        <p id="p2" class="p1">456</p>
        <p id="p3" class="p1">789</p>
    </div>
    <script>        <!--js代码要写在HTML代码下面,否则需要写一个函数在此处调用-->
        var a = document.querySelector("#p2");
        a.innerText = '000';//将id="p2"的节点进行修改
        var b = document.querySelector('.p1');
        b.innerText = '999';//将document中的第一个class="p1"的节点进行修改
    </script>
</body>
</html>

获取父级节点

1. document.getElementById("idname").parentElement;
2. document.getElementById("idname").parentNode;
document.getElementById("idname").offsetParent; // 获取所有父节点,返回数据为数组类型

5.2 更新DOM节点

  1. innerText和innerHTML
var a = document.getElementById('diname');
a.innerText = '123';
a.innerHTML = '<strong>123<\strong>';   //能够转义HTML标签

可以通过获取的id操作相应的标签

例如:通过a.style.color= ‘red’; 更改css样式

  1. replaceChild
node.replaceChild (newnode,oldnode ) //只能使用父节点去操作替换下面的子节点
newnode : 必需,用于替换 oldnode 的对象。 
oldnode : 必需,被 newnode 替换的对象。

eg:

<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>无标题文档</title>
</head>

<body>
    <div>
        <span id="oldnode">JavaScript是一个很常用的技术,为网页添加动态效果</span>
    </div>
    <a href="javascript:replace()"> 将加粗改为斜体</a>

    <script type="text/javascript">
        function replace() {
            var oldnode = document.getElementById('oldnode');
            var newnode = document.createElement("i");
            newnode.innerHTML = oldnode.innerHTML;//将旧节点的内容赋给新节点
            oldnode.parentNode.replaceChild(newnode, oldnode);//替换旧节点原来在网页(DOM数)中的位置
        }
    </script>
</body>
</html>

5.3 删除节点

必须使用父节点删除子节点

object.removeChild();

<body>
    <p id="p1">123</p>
    <p id="p2">456</p>
    <p id="p2">789 </p>
</body>
//方法1:
var self = document.getElementById('p1');
var father = self.parentElement; //获取p1的父节点
father.removeChild(self)//删除p1,可以将self换成p1
//方法2:
var self = document.getElementById('p1');
var father = self.parentElement; //获取p1的父节点
father.removeChild(father.children[0])//注意删除节点的时候,是动态变化的
father.removeChild(father.children[1])//此时删除的是第3个节点:789,因为当删除完第1个节点,第3个节点动态变化为第2个节点了

5.4 创建和插入节点

插入的节点是放在被插入节点的后面

创建节点:document.createElement()

插入节点:document.appendChild()

<!--html文件中的代码-->
<!DOCTYPE html>
<html lang="zn">

<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>Test</title>
</head>
<body>
    <div id="father" class="father">
        <p id="p1" class="p1">123</p>
        <p id="p2" class="p1">456</p>
        <p id="p3" class="p1">789</p>
    </div>
    <script>
        var a = document.getElementById('father');
        var b = document.createElement('p');//创建一个新的节点,该节点为p标签
        b.innerText = 'Hello World!';
        a.appendChild(b);//此时在div的组后添加一个p标签,内容为:Hello World! 可以在浏览器中查看到该p标签
    </script>
</body>
</html>
//插入css样式
var myStyle = document.createElement('style');//创建一个style节点
myStyle.setAttribute = ('type', 'text/css');//设置文档类型,可以省略不写
myStyle.innerHTML = 'body{background-color:green;}';//设置css样式
document.getElementsByTagName('head')[0].appendChild(myStyle);//注意要指明第一个,不然浏览器无法选中
//当然也可以直接使用document.querySelector('head').appendChild(myStyle);

拓展:

在JavaScript中,我们可以使用cloneNode()方法来实现复制节点。

语法:obj.cloneNode(bool)

说明:

参数obj表示被复制的节点,而参数bool是一个布尔值,取值如下:

(1)1或true:表示复制节点本身以及复制该节点下的所有子节点;

(2)0或false:表示仅仅复制节点本身,不复制该节点下的子节点;

使用这些方法去操作DOM节点太繁琐了,所以就诞生了JQuery



六、事件

在JavaScript中,事件往往是页面的一些动作引起的,例如当用户按下鼠标或者提交表单,甚至在页面移动鼠标时,事件都会出现

在这里插入图片描述

6.1 注册事件

给元素添加事件,称为注册事件或者绑定事件

注册事件可分为:传统注册方式方法监听注册方式

  1. 传统注册方式:通常是利用“on”开头的事件+函数进行实践注册

    <!DOCTYPE html>
    <html>
    
    <head lang="en">
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <button class="btns">鼠标点击触发点击事件1</button>
        <button class="btns">鼠标点击触发点击事件2</button>
        <script>
            var x = document.querySelectorAll('button'); //获取所有button节点
            x[0].onclick = function() { //只对第一个button节点进行事件注册
                alert("hi");
            }
        </script>
    </body>
    </html>
    

    注:传统注册方式注册事件具有唯一性,DOM对象只能绑定一个事件,后面绑定的事件会覆盖掉前面绑定的事件,和CSS样式的规则一样

  2. 方法监听注册方式:利用addEventListener()方法(IE9之前的IE浏览器不支持,可以用AttachEvent()代替)W3C新标准

    eventTarget.addEventListener(type,listener[,useCapture])

    • eventTarget:目标对象
    • type:事件类型,click、mouseover等,就是传统事件不带on
    • listener:事件处理函数
    • useCapture:可选参数,false(默认) || ture
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <button class="btns">鼠标点击触发点击事件1</button>
        <button class="btns">鼠标点击触发点击事件2</button>
        <script>
            var x = document.querySelectorAll('button'); //获取所有button节点
            x[0].addEventListener('click', function() {
                alert('这是最新的事件注册方式');
            })
        </script>
    </body>
    </html>
    

    注:

    方法监听注册方式注册事件可以对DOM对象同时绑定多个不同类型的事件,不同事件按顺序执行,相同事件后面的覆盖前面的,和CSS样式的规则一样


6.2 删除事件

将注册的事件删除或解绑

  1. 传统删除事件

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <script>
            var x = document.querySelectorAll('div'); //获取所有button节点
            x[0].style.border = ('1px solid black'); //设置边框,更显眼
            x[0].onclick = function {
                alert('hi');
                x[0].onclick = null;//删除事件
            }
        </script>
    </body>
    </html>
    
  2. 使用removeEventListener()方法删除事件(IE9之前的IE浏览器不支持,可以用detachEvent()代替)

    eventTarget.removeEventListener(type,listener[,useCapture])

    • eventTarget:目标对象
    • type:事件类型,click、mouseover等,就是传统事件不带on
    • listener:事件处理函数
    • useCapture:可选参数,false(默认) || ture
    <!DOCTYPE html>
    <html>
    <head lang="en">
    <meta charset="UTF-8">
    <title>Test</title>
    </head>
    <body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var x = document.querySelectorAll('div'); //获取所有button节点
        x[0].style.border = ('1px solid black'); //设置边框,更显眼
        x[0].addEventListener('click', f);//注:千万不要给函数加小括号
        function f() {
            alert('hi');
            x[0].removeEventListener('click', f);
        }
    </script>
    </body>
    </html>
    

注:要删除事件时,不能使用匿名函数的写法,因为此时用匿名函数会导致无法写明删除的是哪一个事件。同时在不使用匿名函数的写法时,在注册使事件时,不需要给函数加小括号

拓展:

 不加小括号,直接使用函数名是传地址,这个可以用C语言测试,打印输出:printf(“%x\n”,f); ; 而使用小括号是代表调用函数,是传函数的返回值,如果这里加个小括号,就不需要点击事件函数会自动触发

6.3 DOM事件流

  1. 定义:事件发生时会在DOM节点上有一个特定的传递方向,我们将这一个过程称之为DOM事件流
    主要有:捕获阶段、目标阶段、冒泡阶段
  • 捕获阶段:网景最早提出,事件注册时从DOM最顶级节点向下传播,直至待处理事件的节点
  • 目标阶段:传播到待处理事件的节点时称之为目标阶段
  • 冒泡阶段:IE最早提出,事件从目标节点后,逐级向上传播直至DOM最顶级节点
  1. 示意图:假设给div节点绑定一个事件

在这里插入图片描述
在这里插入图片描述

  1. DOM事件流阶段的执行

    • JS代码只能执行捕获阶段或冒泡阶段
    • 传统事件注册和attachEvent方法只能得到冒泡阶段
    • addEventListener方法可以获取捕获阶段和冒泡阶段,当useCapture取值false时,执行冒泡阶段;取值true时执行捕获阶段

    代码测试

    //useCapture默认取值为false时执行冒泡阶段
    //点击son时,会先弹出son,再弹出father
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <div class="father" style="height: 100px;">
            <div class="son" style="height:20px ;"></div>
        </div>
        <script>
            var y = document.querySelector('.son'); 
            y.style.border = ('1px solid black'); //设置边框,更显眼
            y.addEventListener('click', function() {
                alert('son');
            });
            var x = document.querySelector('.father'); 
            x.style.border = ('1px solid black'); //设置边框,更显眼
            x.addEventListener('click', function() {
                alert('father');
            });
        </script>
    </body>
    </html>
    
    //useCapture取值为true时执行捕获阶段
    //点击son时,会先弹出father,再弹出son
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <div class="father" style="height: 100px;">
            <div class="son" style="height:20px ;"></div>
        </div>
        <script>
            var y = document.querySelector('.son'); //
            y.style.border = ('1px solid black'); //设置边框,更显眼
            y.addEventListener('click', function() {
                alert('son');
            }, true);
            var x = document.querySelector('.father'); 
            x.style.border = ('1px solid black'); //设置边框,更显眼
            x.addEventListener('click', function() {
                alert('father');
            }, true);
        </script>
    </body>
    </html>
    

6.4 事件对象

常用事件对象event,这是一个形参通常可以写成:e、evt。再IE6、7、8需要写成window.event,

兼容型写法:e = e | window.event;同时它是浏览器给定的,它是一堆事件的集合
在这里插入图片描述

  1. this和target方法的区别

    this指向我们绑定事件的对象;target指向触发事件的对象

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Test</title>
</head>
<body>
    <div class="father" style="height: 100px;">
        <div class="son" style="height:20px ;"></div>
    </div>
    <script>
        var x = document.querySelector('.father');
        x.style.border = ('1px solid black'); //设置边框,更显眼
        x.addEventListener('click', function(e) {
            // console.log(this);//无论点击son还是father都是输出father
            console.log(e.target)//点击son就输出son的div,点击father就输出father的div
        });
        var y = document.querySelector('.son');
        y.style.border = ('1px solid black'); //设置边框,更显眼
        //y.addEventListener('click', function(e) {
        // console.log(this);
        // console.log(e.target)
        //});
    </script>
</body>
</html>
  1. 阻止默认事件的发生:例如a标签的跳转
  • 对于非IE主流浏览器:

    node.addEventListerner('click',function(e){
        e.preventDefault();
    })
    
  • 对于IE6、7、8

    node.onclik = function(e){
        e.returnvalu;
    }
    
  • 对于传统的注册方式:使用return false;

    node.onclik = function(e){
        return false;
    }
    

    注:return后面的代码是无法继续执行的,但是兼容性很好

  1. 阻止事件冒泡e.stopPropagation (同时可以取消事件捕获)
    点击son时,会先弹出son,再弹出father 只弹出son

    注:哪里需要阻止就往哪里加,因为加在son里面,它只是阻止son不能往上冒泡,如果点击事件发生在father上,且father的父级也绑定了事件,那么仍会冒泡

    //useCapture默认取值为false时执行冒泡阶段
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <div class="father" style="height: 100px;">
            <div class="son" style="height:20px ;"></div>
        </div>
        <script>
            var y = document.querySelector('.son'); 
            y.style.border = ('1px solid black'); //设置边框,更显眼
            y.addEventListener('click', function(e) {
                alert('son');
                e.stopPropagation();
            });
            var x = document.querySelector('.father'); 
            x.style.border = ('1px solid black'); //设置边框,更显眼
            x.addEventListener('click', function(e) {
                alert('father');
            });
        </script>
    </body>
    </html>
    

拓展:

对于IE6、7、8的兼容性写法

if(e && e.stopPropagation){//如果浏览器认识e同时能够识别stopPropagation方法执行
 e.stiopPropagation();
}else{
 window.event.cancelBubble = true;//IE6、7、8只认识cancelBubble方法
}
  1. 事件委托

    事件委托:又称事件代理,在JQuery中称为事件委派。它是利用事件冒泡原理,通过父级节点来操作子节点,让程序做到只操作一次DOM节点就能操作多个DOM节点,能够有效提高程序的性能

    //给父节点绑定事件,通过父节点的事件去改变字节点
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <ul>
            <li>111</li>
            <li>222</li>
            <li>333</li>
        </ul>
        <script>
            var ul = document.querySelector('ul');
            ul.addEventListener('click', function(e) {//点哪个哪个就变色
                var x = e.target;//获取点击的节点
                x.style.backgroundColor = 'green';//改变点击节点的背景色
                // e.target.style.backgroundColor = 'green';
            })
        </script>
    </body>
    </html>
    
  2. 鼠标事件

在这里插入图片描述

//让图片随着鼠标移动而移动
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Test</title>
</head>
<img src="./images/guajian.png" alt="">
<body>
    <script>
        var img = document.querySelector('img');
        document.addEventListener('mousemove', function(e) {
            var x = e.pageX;
            var y = e.pageY;
            img.style.position = 'absolute'; //加绝对定位,让图片移动不影响其他东西
            img.style.left = x - 160 + 'px'; //一定要记得加单位,其中-160是为了让图片居中
            img.style.top = y - 160 + 'px';
        })
    </script>
</body>
</html>
  1. 键盘事件

在这里插入图片描述

注:当使用最新的时间注册方式addEventListener()方法不需要写on。上面三个事件的执行顺序是: k e y d o w n → k e y p r e s s → k e y u p keydown\rightarrow{keypress}\rightarrow{keyup} keydownkeypresskeyup,其中 k e y p r e s s keypress keypress不能识别功能键。同时 k e y u p keyup keyup k e y d o w keydow keydow不区分大小写,但 k e y p r e s s keypress keypress区分

//判断用户按下的键keyCode方法
document.addEventListener('keydown', function(e) {
     alert(e.keyCode);//打印出来的是相应键位的ascii码值
})

拓展:

//1.禁止鼠标右键弹出菜单 contextmenu
<!DOCTYPE html>
<html>

<head lang="en">
 <meta charset="UTF-8">
 <title>Test</title>
</head>
<body>
 <p>dslfjlasjgflsdjgl;</p>
 <script>
     var p = document.querySelector('p');
     p.addEventListener('contextmenu', function(e) {
         e.preventDefault();
     })
 </script>
</body>
</html>
//2.禁止鼠标选中 selectstart
var p = document.querySelector('p');
p.addEventListener('selectstart', function(e) {
e.preventDefault();
})
//3. 获取鼠标焦点
node.focus();

mouseenter和mouseover的区别
使用mouseover时鼠标经过自身盒子或者经过子盒子时都会触发,而mouseenter时只会经过自身盒子时才被触发
原因:mouseenter不会产生事件冒泡,而mouseover会产生事件冒泡
同样的mouseleave同样不会冒泡


6.5 BOM概述

 BOM(Browser Oject Model)即浏览器对象模型,将整各浏览器看作是一个对象。它提供了独立于内容于浏览器窗口进行交互的对象,其核心对象是window,window中的方法是可以不需要使用 对象名.方法()来引用,同时它是所有浏览器对象的父级对象,并且它是由各浏览器厂商在各自的浏览器上自定义的,缺乏一个标准,所以兼容性较差。

 JavaScript的标准是ECMA,DOM的标准的W3C,BOM最初是NEtscape浏览器的标准。需要注意的是:window包括document在这里插入图片描述

  • window是浏览器窗口的一个接口
  • 它是一个全局对象,定义在全局作用域中的变量,函数都会绑定在window对象上,可以通过window.调用它们

回顾:window 作用域

  • load事件和DOMContentLoaded事件的区别:

    • load:等页面内容全部(包括HTML标签、css、图片、音频、视频)加载完毕,在执行相应JS代码
    • DOMContentLoaded:DOM(主要是HTML标签,不包括css、图片、音频、视频)加载完毕,执行相应JS代码
  • risize事件:浏览器窗口发生变化就执行相应JS代码

  • setTimeout(function,time) 定时器

    time单位是毫毛:1s 对应的是 1000,表示间隔多久调用前面的函数,然后就结束 注:只调用一次,前面调用的函数不要加()

    或者写成这样setTimeout(function(){},time);

  • setInterval(funtion,time) 定时器 注:重复调用

    使用方法和setTimeout方法相同,每隔time调用一次

  • clearInterval(setintervalName)

    //设置一个开启和关闭定时器的按钮
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>Test</title>
    </head>
    <body>
        <button>开启定时器</button>
        <button>关闭定时器</button>
        <script>
            var btn = document.querySelectorAll('button');
            var time = null; //一定要将函数的对象time定义成能被clearInterval()方法访问到,不然会报错
            btn[0].addEventListener('click', function() {
                time = setInterval(function() {
                    console.log("How are you?");
                }, 1000);
            });
            btn[1].addEventListener('click', function() {
                clearInterval(time);
            })
        </script>
    </body>
    </html>
    


七、三大常用方法

7.1 offset

可以通过offset动态得到元素的位置、大小等

  • 获取元素距离带有定位的父元素的位置(如果父级没有定位,以上一级有定位为主,都没有则以body为准)
  • 获取元素自身大小(宽度、高度)

注:offset方法的返回值不带单位

  • 相关属性:

在这里插入图片描述

offsetParent返回具有定位的父级标签(如果父级没有定位,以上一级有定位为主,都没有则以body为准),parentNode返回父级标签(无论是否具有定位);具体看代码

<!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>Test</title>
</head>
<style>
    .div1 {
        position: absolute;
    }
</style>
<body>
    <div class="div1">
        <div class="div2">
            <div3 class="div3">
            </div3>
        </div>
    </div>
    <script>
        var node = document.querySelector('div3');
        console.log(node.offsetParent);//返回div1
    </script>
</body>
</html>

动画原理:通过定时器setInterval()不断移动盒子的位置

  • offset与style的区别

在这里插入图片描述

7.2 cilent

通过使用cilent相关属性可以获取元素可视区的相关信息,动态得到元素的边框大小、元素大小

  • cilent相关属性

在这里插入图片描述

7.3 scroll

  • scroll相关属性:

在这里插入图片描述



八、动画

8.1 动画实现的基本原理

动画的实现通常需要搭配定时器setInterval来实现。

实现步骤:

  • 获取当前盒子的位置 (注:需要添加动画的元素一定要加定位relative | absolute | fixed)
  • 获取元素节点,使用style增加距离
  • 利用定时器不断重复上面的操作
  • 可以使用clearInterval清除定时器从而停止动画
<!--一个简单的从左往右的滑块-->
<!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>Test</title>
</head>
<style>
    div {
        position: absolute;
        left: 0px;
        width: 100px;
        height: 100px;
        background-color: pink;
    }
</style>
<body>
    <div></div>
    <script>
        var div = document.querySelector("div");
        setInterval(function() {
            div.style.left = div.offsetLeft + 1 + "px";//只有元素添加了定位才能使用node.style.left
        }, 10);//定时器设置10ms,设置间隔时间越少动画越流畅
    </script>
</body>
</html>

8.2 动画函数封装

使用一个动画函数对某一类动画进行封装,能够减少很多重复的代码。

一般的动画函数需要两个参数:目标对象objtarget移动的距离

速度:relative>absolute|fixed,暂且不知道原因

<!--两个并列的滑块-->
<!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>Test</title>
</head>
<style>
    .div1 {
        position: absolute;
        left: 0px;
        width: 100px;
        height: 100px;
        background-color: pink;
    } 
    .div2 {
        position: relative;<!--比absolute更快?-->
        top: 100px;
        left: 0px;
        width: 100px;
        height: 100px;
        background-color: rgb(192, 255, 194);
    }
</style>
<body>
    <div class="div1"></div>
    <div class="div2"></div>
    <script>
        function move(obj, target) {
            var timer = setInterval(function() {
                if (obj.offsetLeft >= target) {//达到条件就停止动画
                    clearInterval(timer);
                }
                obj.style.left = obj.offsetLeft + 1 + "px";
            }, 50);
        }
        var a = document.querySelector(".div1");
        var b = document.querySelector(".div2");
        move(a, 100);
        move(b, 300);
    </script>
</body>
</html>
  • 优化代码:给不同元素添加不同的定时器
    因为前面的简单封装在调用一次move函数就会在系统中开辟一个空间,很浪费资源

    核心原理:利用JS的动态性的特点,动态给对象添加属性

    即只要将:上面代码的 var timer =...改为 obj.timer =... 以及 clearInterval(timer);改为clearInterval(obj.timer);

  • 完善代码:增加点击触发事件

    因为在实践中大部分情况是通过一个点击事件来触发js动画效果的

    • 在HTML代码中添加一个按钮button

    • 在JS代码中获取button节点:var bnt = document.querySelector("button")

      然后绑定事件:btn.addEventListener(‘click’, function() {

      ​ move(a, 100);

      ​ });

      但是会有一个bug,a会越点越快,因为每点击一次就会增加一个定时器。

      需要在调用函数的最开始加一个清除定时器的代码: clearInterval(obj.timer);

8.3 缓动动画

前面的动画效果都是匀速运动,缓动动画就是让元素的运动速度有所变化,最常见的是减速运动

减速公式: ( 目标值 − 现在的位置 ) / 10 (目标值-现在的位置)/10 (目标值现在的位置)/10 (10是步长,步长越大减速效果更明显)

var step = (target-obj.offsetLest)/10    //向左越来越慢移动

上面step存在小数问题,因为除法是直接舍去小数部分的,会导致实际移动距离小于目标移动距离

对于正方向的移动,采用向上取整,对于负方向的移动,采用向下取整

var step = (target-obj.offsetLeft)/10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);

8.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>Test</title>
</head>
<style>
    .div1 {
        position: absolute;
        left: 0px;
        width: 100px;
        height: 100px;
        background-color: pink;
    }
</style>
<body>
    <div class="div1"></div>
    <script>
        function move(obj, target, callback) {
            obj.timer = setInterval(function() {
                if (obj.offsetLeft > target) {
                    clearInterval(obj.timer);
                    if(callback){//判断回调函数是否传进来。可以不加判断,但是严谨一点加好
                        callback();//当判定动画结束,就立刻执行该回调函数
                    }
                }
                obj.style.left = obj.offsetLeft + 2 + "px";
            }, 15);
        }
        function f() {//定义回调函数
            alert("动画已结束")
        }
        var a = document.querySelector(".div1");
        move(a, 1000, f);
    </script>
</body>
</html>
  • 10
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知识汲取者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值