js基础(ecamscript语法+DOM+BOM)

一、初识javascript

  1. Javascript是什么
    1. 运行在客户端的脚本语言
    2. 脚本语言:不需要编译,运行过程中由Js解释器(js引擎)逐行来进行解释并执行
    3. Node.js可用于服务端的编程
    4. 高级编程语言
  2. js作用
    1. 表单动态检验(js产生的最初目的)
    2. 网页特效
    3. 服务端的开发(node.js)
    4. 桌面程序(Electron)
    5. App(Cordova)
    6. 控制硬件-物联网(Ruff)
    7. 游戏开发(cocos2d-js)
  3. 浏览器执行Js的方式
    1. 浏览器分为两部分:渲染引擎和js引擎
    2. 渲染引擎:用来解析Html和css,即为内核,比如:chrome浏览器的blink,老版本的webkit
    3. js引擎:js解释器,用来读取网页中的js代码,对其处理后运行,比如:chrome:V8,也即:执行代码时逐行解释每一句源码(转换为机器语言),然后由计算机去执行,所以js语言归为脚本语言,会逐行解释执行
      1. 运行js分为两步
        1. 预解析
        2. js代码执行
  4. js组成
    1. ECMAScript(JavaScript语法)
      1. Javascript(网景公司)和jscript(微软公司)是ecmascript的实现和扩展
      2. 规定了js的编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套js语法工业标准
    2. DOM(页面文档对象模型)
      1. 是w3c组织推荐的处理可扩展标记语言的标准编程接口
      2. 通过dom提供的接口可以对页面上的各种元素进行操作
    3. BOM(浏览器对象模型)
      1. 提供了独立于内容的、可以与浏览器窗口进行互动的对象结构,通过bom可以操作浏览器窗口。
    4. 其中DOM 和BOM都属于WebAPIS
      1. API 应用程序编程接口
      2. webApi是浏览器提供的一套操作浏览器功能和页面元素的API
  5. 规定
    1. html使用双引号,js使用单引号
  6. 输入输出
    1. alert()
    2. console.log()
    3. prompt()输入
    4. 以上都是归属于浏览器的
    5. doucument.write()向页面的Body标签输入内容

二、ecmascript语法

2.1变量
  1. 声明:var

  2. 同时声明多个变量

    var name_my = 'zt',
        age = 18,
        money = 20;
    // 效果跟以下一样
    var name_my = 'zt';
    var age = 18;
    var money = 20;
    
    var age1 = age2 = age3 = 2;
    //效果跟以下一样
    var age1 = 2;
    age2 = 2;
    age3 = 2;
    
  3. 声明变量的特殊情况

    1. 只声明不赋值直接使用 undifined
    2. 不声明不赋值直接使用 报错
    3. 不声明直接赋值使用 可以
      1. 不声明的变量作为window对象的属性
      2. 可以删除,但是声明的变量不可以删除
2.2数据类型
  1. 总览

datatype_01

  1. 数字型数据

    1. 二进制 0b开头
    2. 八进制 0开头
    3. 十六进制 0x开头
    4. 数值中的最大值和最小值
      1. Number.MAX_VALUE
      2. Number.MIN_VALUE
    5. 三个特殊值
      1. Infinity无穷大
      2. -Infinity无穷小
      3. NaN 非数字数据
        1. 判断当前数据是否为非数字 isNaN(data)
        2. 是非数字 true
  2. 字符串类型

    1. 双引号
    2. 单引号
    3. js推荐为单引号
    4. 引号匹配为就近匹配
      1. 外双内单
      2. 内双外单
    5. 字符串换行
      1. \n换行
      2. \\斜杠
      3. \t tab缩进
      4. \b空格
    6. 字符串长度
      1. length属性
      2. ‘hhh’.length
    7. 字符串拼接
      1. +
  3. 布尔值类型

    1. true参与加法运算当1 看

    2. false参与加法运算当0看

    3. console.log(true + 1);// 2 
      console.log(false + 0);// 1
      
  4. undefined 类型数据

    1. 出现场景:声明但是没有赋值的变量直接拿来使用的时候 undefined

    2. 与 数值相加-> NaN

    3. var num;
      console.log(num);
      num = undefined;
      console.log(num + 'pink');//undefinedpink
      console.log(num + 1);//NaN
      console.log(true + num);//NaN
      
  5. null 类型数据

    1. 里面存储的是空值

    2. 与数值相加 等于数值

    3. var num = null;
      console.log(num + 1);//1
      console.log(num + true);//true
      
  6. 获取数据 数据类型

    1. typeof

    2. console.log(typeof null);//object
      
  7. 字面量

    1. 源代码中一个固定值的表示方法
  8. 数据类型的转换

    1. 转换为字符串类型

      1. toString() 显示转换

      2. String() 强制转换

      3. + 隐私转换

      4. var num = 19;
        console.log(num.toString())
        console.log(String(true))
        console.log(null + '')
        
    2. 转换为数值类型

      1. parseInt()转换为整数

        console.log(parseInt('3.14'))// 3
        console.log(parseInt('3.94'))// 3 不会进位
        console.log(parseInt('120px'))// 120 截取
        console.log(parseInt('pa120'))// NaN
        
      2. parseFloat转换为浮点数

        情况与parseInt()类似

      3. Number()强制转换(int和Float都可以 但是不支持截取)

        console.log(Number('1.34')) // 1.34
        console.log(Number('1.34px')) // NaN
        
      4. - * / 隐私转换

        // - * /
        console.log('123' - 120);// 3
        
    3. 转换为Boolean数据类型

      1. Boolean()
      2. 代表空、否定的值都转换为false(’’ 0 NaN null undefined)
      3. 其他的都为true
2.3标识符
1. 开发人员为变量、属性、函数、参数取的名字

2. 标识符不能为关键字/保留字
2.4运算符
  1. 算术运算符

    1. 注意点
      1. 浮点数进行运算存在精度问题 不准确
      2. 避免浮点数比较
      3. 0.1 + 0.2 == 0.3 //false
  2. 递增/递减运算符

    1. a++ ++a
    2. a-- --a
  3. 比较运算符

    1. == 默认会转换数据类型

      console.log(18 == '18'); // true
      
    2. === 全等 要求数据类型也需要一致

  4. 逻辑运算

  5. 赋值运算符 +=

  6. 运算符优先级

在这里插入图片描述

2.5流程控制分支
  1. 顺序结构

  2. 分支结构

    1. if语句

      if() {
              
              
      
      } else if() {
              
              
      
      } else {
              
              
      
      }
      
    2. switch语句

      1. 注意点
        1. 匹配关系为全等
    3. 三元表达式

      条件表达式?表达式1:表达式2
      
  3. 循环

    1. for循环
    2. while循环
    3. do…while循环
  4. continue

  5. break

2.6命名规范
  1. 变量 用名词
  2. 函数名称用动词
  3. 操作符规范 操作符两侧有空格
  4. 单行注释规范 单行注释前面注意有一个空格
  5. 其他规范
    1. if () 括号两侧预留空格
    2. for () 括号两侧预留空格
2.7数组
  1. 创建数组

    1. new方式创建数组

      var var_a = new Array(2);// 创建两个空数组
      var var_b = new Array(2,4);// 创建包含两个元素 2,4的数组[2,4]
      
    2. 字面量创建数组

      var var_b = [];
      
  2. 可以存放任意的数据类型数据

  3. 获取数组的长度 arr.length属性获取

  4. 新增数组的元素

    1. 修改length的长度

      增加的元素位置为undefined

    2. 修改数组索引号来追加数组元素

      不要直接将数组名进行赋值,原因:数组名即为变量 直接赋值改变了变量的存储数据
      es5新增数组方法

  5. 迭代(遍历方法)

    1. forEach()

      1. 语法:

        array.forEach(function(currentValue,index,arr))	
        
      2. currentValue:数组当前项的值

      3. Index:数组当前项的索引

      4. arr:数组对象本身

         var arr = [1,2,3];
            arr.forEach(function (value, index, array) {
                  
                  
                console.log(value + index + array);
            })
        
    2. map()

      1. 存储键值对的方式,可以将数组转换为map对象之后再采用map遍历方法进行遍历,但是不怎推荐使用这种方式,原因是数组有自己的方式进行元素的遍历
    3. filter() 筛选数组

      1. 语法:

        arr.filter(function(currrentValue,index,arr))
        
      2. 返回一个满足条件的新数组

      3. currentValue:数组当前项的值

      4. Index:数组当前项的索引

      5. arr:数组对象本身

      6. var arr = [1,2,3,-8,-4,-5,-2,-1];
        console.log(arr.filter(function (value, index, array) {
                  
                  
            var temp = value * index + 2;
            return temp > 0;
        }));
        
    4. some() 查找某个元素是否存在于该数组中

      1. 语法

        arr.some(function(currrentValue,index,arr))
        
      2. currentValue:数组当前项的值

      3. Index:数组当前项的索引

      4. arr:数组对象本身

      5. 返回布尔值,找到第一个满足要求的元素即会返回

         var arr = [1,2,3,-8,-4,-5,-2,-1];
            console.log(arr.some(function (value, index, array) {
                  
                  
                var temp = value * index + 2;
                return temp > 0;
            }));
        
    5. every() 判断是否所有的元素都符合要求

      1. 语法

        arr.every(function(currrentValue,index,arr))
        
      2. currentValue:数组当前项的值

      3. Index:数组当前项的索引

      4. arr:数组对象本身

      5. 返回布尔值,只有所有的数组元素都满足要求才返回true

  6. es6扩展方法

    1. find()

      1. 用于找出第一个符合条件的数组成员,如果没有找到返回undefined

      2. 用例:

        let arr = [1,2,3];
        console.log(arr.find(item => item < 3));
        let arr2 = [{
                  
                  
                id: 1,
                uname: 'zt'
            },{
                  
                  
                 id: 2,
                 uname: 'zztt'
            }
        ];
         console.log(arr2.find((item,index) => item.id == 2));// 其中item.id == 2为查找条件(返回查找条件)
        
    2. findindex()

      1. 用于找出第一个符合条件的数组成员的索引,如果没有找到返回-1
      2. 用法与find一样
    3. includes()

      1. 表示某个数组是否包含给定的值,返回布尔值

      2. 用例:

        console.log([1,2,3].includes(2));// true
        
      3. 注:

        1. 对象的比较看的是地址,因此不容易进行查找

          console.log([{
                      
                      id:1},2,3].includes({
                      
                      id:1}));// false
          
2.8函数
  1. 函数的声明

    1. 命名函数
    function 函数名() {
          
          
        //函数体
    }
    
    1. 匿名函数 函数表达式的形式进行声明

      var 变量名 = function() {
              
              
          
      };
      
    2. 通过new Function()方式创建 不推荐使用 太麻烦

      1. 每个函数都是Function函数的实例对象

      2. 每个函数都是一个对象,因此也具有原型对象等属性对象

    var func = new Function('参数1','参数2','函数体');
    
  2. 函数形参和实参个数匹配的问题

    1. 实参个数大于形参个数 根据形参个数来进行一一匹配
    2. 实参个数小于形参个数 多余的形参为未声明的变量 undefined 如果直接使用 可能会产生NaN的情况
    3. arguments使用
      1. 场景:当不确定实参个数的情况下,通过arguments进行获取
      2. js中,arguments为当前函数的内置对象,对象中存储了传递的所有实参
      3. arguments实际上是一个伪数组
        1. 具有length属性
        2. 按索引方式存储数据
        3. 不具有数组的push,pop等方法
  3. return返回值

    1. return 只返回一个值 即使多个值用逗号隔开,但是只返回最后一个值

    2. function test() {
              
              
          return 1,2;
      }
      
      console.log(test());//2
      
    3. 如果函数内部没有写return 但是还是使用了函数的返回机制 则返回的是undefined

      function test() {
              
              
      }
      
      console.log(test());//undefined
      
  4. 作用域 es6之前

    1. 全局作用域 scrptit标签之中

    2. 局部作用域

    3. 没有块级作用域(es6之前) {}包含,即{}定义的变量 其内定义的变量 在{}外是可以进行使用的

      if () {
              
              
          var num = 1;
          }
      console.log(num);// 1 可以进行使用
      
  5. 作用域链

    对于作用域嵌套级联的情况,通过链式就近查找的方式进行查找

2.9预解析
  1. 定义

    js引擎会把js里面所有的var 还有function提升到当前作用域的最前面

  2. 分类

    1. 变量预解析(变量提升)

      1. 将所有变量声明提升到当前的作用域最前面 不进行赋值操作

      2. 场景一

        console.log(num);// 结果为undefined
        var num = 12;
        
        //变量提升过程
        var num;
        console.log(num);
        num = 12;
        
      3. 场景二

        fun();// 报错
        var fun = function() {
                  
                  
            console.log(1);
        }
        
        // 函数提升过程
        var fun;
        fun();
        fun = function() {
                  
                  
            console.log(1);
        }
        
    2. 函数预解析(函数提升)

      1. 将所有的函数声明提升到当前作用域的最前面 不调用函数

      2. 不管在函数之前调用还是在调用之后使用,都是可以使用的

        function fun() {
                  
                  
            console.log(1);
        }
        fun();// 正常调用
        
        fun();// 正常调用
        function fun() {
                  
                  
            console.log(1);
        }
        
2.10对象
  1. 创建对象

    1. 字面量的形式创建

      var obj = {
              
              	
          uname: 'zt',
          age: 18,
          sayHi: function() {
              
              
              consoloe.log('hi~');
          }
      }
      
      1. 使用
      console.log(obj.uname);
      console.log(obj['uname']);
      
    2. new Object()方式创建对象

      var obj = new Object();
      obj.uname = 'zt';// 追加属性的方式进行添加对象属性
      obj.sayHi = function() {
              
              
          console.log('hi');
      }
      
  2. 采用构造函数的方式进行创建对象(类似于java类)

    1. 方式

      function Obj(uname,age) {
              
              
          this.uname = uname;
          this.age = age;
      }
      
      var obj = new Obj('name',18);
      
    2. 注意点:

      1. 可以作为函数一样进行考虑:arguments一样适用,参数不对应的情况
      2. 构造函数名(类名)首字母大写
  3. es6,通过class关键字进行创建

  4. 定义新属性/修改原有的属性

    1. 通过点语法
    2. es5中方法:Object.defineProperty(obj,prop,descriptor),只有通过这个方式进行设置,以下的参数的默认值才会对对象有效
    3. obj:修改的对象
    4. prop:目标属性
    5. descriptor:以对象形式{}书写
      1. value:设置属性的值,默认为undefined
      2. wirtable:值是否可以重写,true|false默认为false
      3. enumerable:目标属性是否可以被枚举。true|false默认为false,则不允许遍历
      4. configurable:目标属性是否可以被删除或是否可以再次修改特效true|false,默认为false,则不允许修改特性
2.11内置对象
  1. Date

    1. 时间戳 距离 1970年1月1日过了多少毫秒数

      1. 通过valueOf() getTime()获得

        var date = new Date();
        console.log(date.valueOf());
        console.log(date.getTime());
        
      2. 简单写法 +new Date()获取

        console.log(+new Date());
        
      3. H5 新增

        console.log(Date.now());
        
  2. Array

    1. 检测是否为数组

      1. instanceof

        var arr = [];
        console.log(arr instanceof Array);// true
        
      2. Array.isarray() H5新增 ie9以上版本才支持

        var arr = {
                  
                  };
        console.log(Array.isArray(arr));// false
        
    2. 增加/删除数组元素

      1. 添加

        1. push
        var arr = [];
        arr.push(2,'pink');// 返回新数组长度
        
        1. unshift 数组开头添加元素
        var arr = [];
        arr.unshift(2,'pink');// 返回新数组的长度
        
      2. 删除

        1. pop 返回删除的元素
        2. shift 返回删除的元素
      3. 数组排序

        1. reverse() 翻转

        2. sort() 排序

          1. 存在问题 只能对个位数进行排序

          2. 解决

            var arr = [1,3,56,12];
            arr.sort(function(a,b) {
                          
                          
            return a - b;
            })
            
      4. 查找某个数组元素返回索引号

        1. indexOf() 从头开始查找
        2. lastIndexOf() 从尾开始查找
      5. 数组转换为自符串

        1. toString() 默认逗号分隔
        2. join() 可以跟分隔符
  3. 字符串

    1. ·基本包装类型

      将简单的数据类型包装成复杂的数据类型 ,即打造了三个引用类型 String Number Boolean

    2. 存在不可变性 开辟新的内存空间 字符串的修改不会改变原字符串

    3. 返回字符位置

      1. indexOf()
      2. lastIndexOf()
    4. 根据位置返回字符

      1. charAt()
      2. charCodeAt() 返回字符的ASCII
      3. str[index] H5新增
    5. 转换为数组

      split()

    6. 去除左右两边空格 返回新的字符串

      trim()

    7. es6新增方法

      1. startWith():表示参数字符串是否在原字符串的头部,返回布尔值

      2. endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值

      3. repeat():表示将原字符串重复n次,返回一个新字符串

         'x'.repeat(n);
        
2.12 简单类型
  1. 简单类型

    基本数据类型/值类型,在存储的时候存储的是数据本身

    string number boolean undefined null

  2. 复杂类型

    引用类型,在存储变量的时候存储的仅仅是地址

    先在栈中存放地址 十六进制表示 然后这个地址指向堆里面的数据

    复杂类型传参传递的是地址

2.13堆栈
  1. 由操作系统自动分配释放存放函数的参数值、局部变量的值等。简单数据类型存放到栈中
  2. 存储复杂类型,一般由程序员分配释放,若不释放,由垃圾回收机制回收。复杂数据类型存放到堆里面。
  3. js没有堆栈的概念

三、DOM

3.1简介

处理可扩展标记语言的标准编程接口

3.2DOM树
  1. 文档

    一个页面就是一个文档,DOM中使用document表示

  2. 元素

    页面中的所有标签都是元素,DOM中使用element表示

  3. 节点

    网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示

  4. 以上所有内容被DOM都视为对象

3.3获取页面元素
  1. 获取ID元素

    1. document.getElementById() 返回element对象

    2. 通过console.dir() 打印返回的元素对象,更好的查看属性和方法

    3. 注意

      1. 由于html文档是自上而下进行解析的,因此包含页面元素的获取js文件需要在整个网页加载完成之后进行引入才可以获取页面元素

      2. html

        <!DOCTYPE html>
        <html lang="en">
        
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>practice1</title>
            <link href="../css/practive1.css" rel="stylesheet"/>
        </head>
        
        <body>
        <div>
            <a href="" id="phone">手机 电话卡</a>
            <a href="">电视 盒子</a>
            <a href="">笔记本 平板</a>
            <a href="">出行 穿戴</a>
            <script type="text/javascript" src="../js/practice1.js"></script>
        </div>
        </body>
        
        </html>
        
  2. 根据标签名获取

    1. 获取页面中某个元素

      console.dir(document.getElementByTagName('ul'));// 返回的是当前标签名元素的伪数组
      
    2. 通过对象父元素进行获取

      console.dir(document.getElementById('id').getElementByTagName('ul'));// 返回的是当前标签名元素的伪数组
      
  3. 根据类名获取页面元素

    console.dir(document.getElementByClassName('id'));// 返回的是当前标签名元素的伪数组
    
  4. h5新增选择器

    1. document.querySelector() 选择符合选择器的第一个元素

    2. document.querySelectorAll() 选择符合选择器的所有元素

    3. 以上参数符合css选择器方式

    4. console.log(document.querySelector('a'));
      console.log(document.querySelectorAll('#phone'));
      
  5. 获取特殊元素

    1. 获取Body元素

      console.log(document.body);
      
    2. 获取html元素

      console.log(document.documentElement);
      
  6. 点语法:标签对象.自定义属性 = “自定义属性值”

<div></div>
var div = document.querySelector('div');
div.index = 1;// 添加自定义属性
3.4 元素操作
  1. 组成

    1. 事件源 事件被触发的对象
    2. 事件类型
    3. 事件处理程序 通过函数赋值的方式完成
  2. 例子

    document.querySelector('button').onclick = function () {
          
          
        alert('我被点击了 呜呜呜');
    }
    
  3. 操作元素

    1. 利用DOM操作元素来改变元素里面的内容、属性

    2. 改变元素内容

      1. innerText
        1. 不识别html标签
        2. 非标准
        3. 去除空格和换行
      2. innerHTML
        1. 识别html标签
        2. W3C标准
        3. 保留空格和换行
        4. 推荐使用
    3. 修改元素属性 src alt id等等

      document.querySelector('button').onclick = function () {
              
              
          document.querySelector('#phone').href = 'https://www.baidu.com';
          this.disabled = true;// this 指向事件的调用者
      }
      
    4. 改变样式属性

      1. element.style

        1. 属性采取的是驼峰命名法

        2. 改变的是行内样式 权重更高

        3. 适合改变样式比较少的情况

        4. document.querySelector('#phone').onclick = function () {
                      
                      
              this.style.width = '200px';
              this.style.backgroundColor = 'red';
          }
          
      2. element.className

        1. 适合改变的样式特别多的情况
        2. 覆盖原来的类名
    5. 获取元素属性

      1. element.属性 获取Js内置属性

      2. element.getAttribute(‘属性’)

        1. 主要获取自定义属性

        2. <div index="1"></div>
          console.log(document.querySelector('div').getAttribute('index'));// 1
          
    6. 设置元素属性

      1. element.属性 = new属性

      2. elment.setAttribute(‘属性’,‘new属性’)

      3. <div index="1" class="nav"></div>
        var div = document.querySelector('div');
        div.className = 'newNav';
        div.setAttribute('class','newNav');// class比较特殊 其他都是按名字设置
        
    7. 移除属性

      1. element.removeAttribute(‘属性’);
    8. H5自定义属性

      1. 自定义属性目的

        为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。

      2. 规范:data-名称

        原因:为了更好的区分是内置属性还是自定义属性的方法

      3. 获取自定义属性 ie11以上支持

        element.dataset.名称或者element.dataset[‘名称’]

        <div data-index="1" data-my-name="zt"></div>
        var div = document.querySelector('div');
        console.log(div.dataset.index);
        console.log(div.dataset.myName);// 争对多个命名 采用驼峰命名法
        
3.5节点操作
  1. 使用原因:

    由于文档内容都可以视为节点,并且相对于DOM操作,节点操作的逻辑性更强

  2. 节点至少拥有以下几个基本属性

    1. 节点类型nodeType
      1. nodeType = 1 元素节点
      2. nodeType = 2 属性节点
      3. nodeType = 3 文本节点(文字、空格、换行等)
    2. 节点名称
    3. 节点值
  3. 节点层级

    1. 父级节点

      1. node.parentNode

      2. 返回某节点的父节点,即离当前节点最近的一个节点

      3. <div class="demo">
            <div class="child"></div>
        </div>
        var child = document.querySelector('.child');
        console.log(child.parentNode); // 得到的是包含子节点在内的父节点
        
    2. 子节点

      1. childNodes 标准
        1. 返回包含指定节点的子节点的集合,其中包含了元素节点、文本节点等,需要过滤(通过nodeType来过滤)之后才能使用,一般很少使用
      2. children 非标准
        1. 获取节点的子节点集合,只包含元素节点,常用
        2. 不存在兼容性问题
    3. 获取第一个子节点/最后一个子节点

      1. firstChild/lastChild
        1. 获取的子节点包括文本节点和元素节点
      2. firstElementChild/lastElemenChild
        1. 获取的子节点只包括元素节点
        2. 但是只有ie9以上才支持
        3. 总结:采用children方式获取第几个节点
    4. 兄弟节点

      1. 上一个兄弟节点/下一个兄弟节点
        1. previousSiblings/nextSibings
          1. 获取包括文本节点等的所有节点
        2. previousElementSiblings/nextElementSibings
          1. 获取元素节点
          2. ie9以上支持
    5. 创建元素节点

      1. document.createElement
        
    6. 添加元素节点

      1. 追加元素节点

        1. node.appendChild(newNode);
          
      2. 在某个子节点前面添加元素节点

        1. node.insertBefore(newNode,某个子节点);
          
    7. 删除元素节点

      1. node.removeChild(child); 返回删除的节点元素
    8. 克隆节点

      1. node.cloneNode();返回调用该方法的节点的一个副本
      2. 如果括号为空/为false,则为浅拷贝,之复制标签不复制里面的子节点
      3. 只有当括号内为true,才为深拷贝,拷贝标签以及其内的所有内容
    9. 三种创建元素节点方式的区别

      1. document.write()

        1. 当页面加载完成之后,也即页面文档流加载完毕之后,再调用该语句会造成页面重绘

        2. document.write('<a href="#">删除</a>')
          
      2. element.innerHTML

        1. 采取字符串拼接的方式 时间为3秒 效率很低 原因:每次创建新的字符串都需要开辟新的内存空间,很消耗内存
        2. 采取数组形式拼接 时间为几毫秒 效率很高
      3. document.createElement()

        1. 时间为几十毫秒
      4. 总结: 不同浏览器下,innerHTML效率比createElement高

3.6高级事件
3.6.1注册事件(绑定事件)/ 删除事件
  1. 概述

    给元素添加事件,包括传统方式和方法监听注册方式

  2. 传统方式

    1. 利用on开头的事件:onclick

    2. 方式有两种

      1. <button onclick="alert('hi')"></button>
        
      2. btn.onclick = function() {
                  
                  }
        
    3. 特点:

      1. 注册事件的唯一性
      2. 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
  3. 方法监听注册方式

    1. w3c标准

    2. 利用addEventListener()方式进行监听注册

    3. ie9版本以上支持

    4. ie9版本以下采用attachEvent() // 但是找不到这个函数,不知道为啥

      1. 非标准,经量不要在生产环境中使用

      2. 只适用于IE浏览器

      3. 使用方式

        1. eventTarget.attachEvent(eventNameWithOn,callback);
          
        2. 参数说明

          1. eventNameWithOn:事件类型字符串,比如:onclick,此处要带上On
          2. callback:事件处理函数
    5. 特点

      1. 同一个元素同一个事件可以注册多个监听器
      2. 按照注册顺序依次执行
    6. 用法

      1. eventTarget.addEventListener(type,listener[,useCapture])
        
      2. 将指定得监听器注册到eventTarget(目标对象上),当该对象触发指定得事件时,就会执行事件处理函数

      3. 参数说明

        1. type:事件类型字符串,比如:click,此处不带on
        2. listener:事件处理函数,事件发生时,会调用该监听函数
        3. userCaptuer:可选参数,为一个布尔值,默认为false,涉及到DOM事件流。
    7. 注册事件兼容性解决方案

      1. 兼容性处理原则:首先照顾大多数浏览器,再处理特殊浏览器

      2. /**
         * 注册事件
         * @param element 元素对象
         * @param eventName 事件名称
         * @param fn 注册监听事件
         */
        function addEventListener(element,eventName,fn) {
                  
                  
            // 判断当前浏览器是否支持 addEventListener 方法 (ie9以上)
            if (element.addEventListener) {
                  
                  
                element.addEventListener(eventName,fn);
            } else if (element.attachEvent) {
                  
                  
                // ie9 以下且为IE浏览器
                element.attachEvent('on' + eventName,fn);
            } else {
                  
                  
                // 通用
                element['on' + eventName] = fn; // 类似于 element.onclick = fn;
            }
        }
        
    8. 删除事件

      1. 应用场景:

        由于某对象绑定某注册事件之后,直到页面销毁才消失,当只需要一次事件调用得时候,就需要删除事件

      2. 删除事件方式

        1. 传统注册方式

          1. btn.onclick = null
            
          2. var btn = document.querySelector('button');
            
            btn.onclick = function () {
                          
                          
                alert('1');
                btn.onclick = null; // 解绑函数
            }
            
        2. 方法监听注册方法

          1. eventTarget.removeEventListener(type,listener[,useCapture]);
            
          2. var btn = document.querySelector('button');
            
            function fn() {
                          
                          
                alert('1');
                btn.removeEventListener('click',fn);
            }
            
            btn.addEventListener('click',fn);
            
          3. eventTarget.detachEvent(eventNameWithOn,callback);
            
          4. var btn = document.querySelector('button');
            
            function fn() {
                          
                          
                alert('1');
                btn.detachEvent('click',fn);
            }
            
            btn.attachEvent('click',fn);
            
    9. 删除事件兼容性解决方案

      /**
       * 删除事件
       * @param element 元素对象
       * @param eventName 事件名称
       * @param fn 注册监听事件
       */
      function removeEventListener(element,eventName,fn) {
              
              
          // 判断当前浏览器是否支持 removeEventListener 方法 (ie9以上)
          if (element.removeEventListener) {
              
              
              element.removeEventListener(eventName,fn);
          } else if (element.detachEvent) {
              
              
              // ie9 以下且为IE浏览器
              element.detachEvent('on' + eventName,fn);
          } else {
              
              
              // 通用
              element['on' + eventName] = null; 
          }
      }
      
      
3.6.2 DOM事件流
  1. 概述

    1. 事件流

      描述的是页面中接收事件的顺序

    2. DOM事件流

      事件发生时会在元素节点之间按照特点的顺序传播,该传播过程称为DOM事件流

  2. 分为三个阶段 只是一个过程而已

    1. 捕获阶段
      1. 网景公司最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程。
    2. 当前目标阶段
      1. 当前元素
    3. 冒泡阶段
      1. IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程。
      2. DomthingThread_01
  3. 注意

    1. JS代码只能执行捕获或者冒泡其中的一个阶段,但是如果写了本质上是可以按照不同阶段来执行的

    2. onclick和attachEvent只能得到冒泡阶段

    3. addEventListener(type,listener[,useCapture])第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;如果是false,表示在事件冒泡阶段调用事件处理程序。

    4. 实际开发中常关注事件冒泡

    5. 有些事件没有冒泡,比如:onblur onfocus onmounseenter onmouseleave

3.6.3 事件对象
  1. 概述

    侦听函数的形参,事件发生的一系列相关数据的集合,由系统自动创建

  2. 例子

    var son = document.querySelector('.son');
    
    son.onclick = function (e) {
          
          
        console.log(e);
    }
    
  3. 存在兼容性问题,ie6/7/8 通过window.event获取,而不是通过侦听函数形参进行获取

    1. 如果使用eventTarget.onclick = function() {}写法,兼容性写法如下:

      son.onclick = function (e) {
              
              
          e = e || window.event;
      }
      
  4. 事件对象常见属性和方法

    1. e.target 返回触发事件的对象(元素)

      1. 与this不同点在于:this 返回的是绑定事件的对象(元素) this 与 e.currentTarget获得内容是一致的

      2. 例子:

        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        var ul = document.querySelector('ul');
        ul.addEventListener('click',function (e) {
                  
                  
            console.log(e.target); // 如果点击的是li标签 返回的是li
            console.log(this); // 返回绑定事件对象 ul
        })
        
      3. 兼容性问题

        1. ie6/7/8不支持 只能通过window.event.srcElement获取

        2. 解决兼容性

          ul.onclick = function (e) {
                      
                      
              e = e || window.event;
              var target = e.target || e.srcElement;
              console.log(target);
          }
          
    2. e.type 返回事件类型

    3. e.preventDefault() 阻止默认行为(事件)

      1. 即:链接不跳转,提交按钮不能提交

      2. 案例:

        a.addEventListener('click',function (e) {
                  
                  
            e.preventDefault();
        })
        
      3. 传统注册方式

        a.onclick = function (e) {
                  
                  
            e = e || window.event;
            // 普通浏览器 可采用此方式
            e.preventDefault();
            // 低版本浏览器 ie6/7/8 可采用此属性
            e.returnValue;
            // 没有兼容性问题, 但是也仅仅只限于传统的注册方式  并且之后的代码也不再执行
            return false;
        }
        
    4. e.stopPropagation() 阻止冒泡

      1. 阻止当前对象事件冒泡 ,对当前事件对象添加

      2. 案例

        a.addEventListener('click',function (e) {
                  
                  
            alert('dianji');
            e.stopPropagation();
        })
        
      3. 兼容性问题

        1. ie6/7/8采用e.cancelBubble属性的方式进行阻止冒泡行为

        2. a.onclick = function (e) {
                      
                      
              if (e && e.stopPropagation) {
                      
                      
                  e.stopPropagation();
              } else {
                      
                      
                  window.event.cancelBubble = true;
              }
          }
          
    5. 事件委托

      1. 也称为事件代理,在jQuery里面称为事件委派

      2. 事件委托原理

        给父节点添加事件侦听器,利用事件冒泡影响每一个子节点。

        相对于以前给每个子节点单独设置事件监听器不同的是,此时事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点

        例子:给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li,事件会冒泡到ul上,ul有注册事件,便会触发事件监听器

      3. 事件委托的作用

        只操作了一次DOM,便提升了程序的性能

3.6.4常用的鼠标事件

1.mouseThing

  1. 禁止鼠标右键菜单

    1. contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下菜单

    2. document.addEventListener('contextmenu',function (e) {
              
              
          e.preventDefault();
      })
      
  2. 禁止鼠标选中

    1. selectstart

    2. document.addEventListener('selectstart',function (e) {
              
              
          e.preventDefault();
      })
      
  3. mouseenter与mouseover的区别

    1. 都是鼠标移到元素上时会触发事件
    2. 区别在于:mouseenter/mouseleave不会冒泡,而mouseover/mouseout会冒泡
3.6.5鼠标事件对象
  1. MouseEvent
  2. e.clientX/e.clientY
    1. 返回鼠标触发事件处相对于浏览器窗口可视区的X/Y坐标
  3. e.pageX/e.pageY
    1. 返回鼠标触发事件处相对于文档页面的X/Y坐标 ie9以上支持
  4. e.screenX/e.screenY
    1. 返回鼠标相对于电脑屏幕的X/Y坐标
    2. mouseEvent
3.6.6常用键盘事件
  1. keyup 按键弹起时执行
  2. keydown 按键按下时执行
  3. keypress 按键按下时执行 但是不识别功能键 ctrl shift 左右箭头等
  4. 三个执行顺序keydown -> keypress -> keyup
3.6.7键盘事件对象
  1. keyBoardEvent
  2. e.key获取按下得建
  3. e.keyCode得到相应键得ASCII值
  4. keyup 和 keydown 事件不区分字母大小写
  5. keypress事件区分字母大小写

四、BOM

4.1概述
  1. BOM提供独立于内容而与浏览器窗口进行交互的对象,其核心对象是window

  2. BOM缺乏标准,javascript语法的标准化组织是ECMA,DOM的标准化组织是W3C,BOM最初是NEtscape浏览器标准的一部分

  3. 与DOM的区别

    DOM BOM
    文档对象模型 浏览器对象模型
    DOM将文档当作一个对象看待 BOM把浏览器当作一个对象看待
    DOM的顶级对象是document BOM的顶级对象是window
    DOM主要学习的是操作页面元素 BOM学习的是浏览器窗口交互的一些对象
    DOM是W3C标准规范 BOM是浏览器厂商在各自浏览器上定义的,兼容性较差
4.2 BOM的组成

BOMcompent_01

  1. window对象是浏览器的顶级对象,具有双重角色
  2. 是js访问浏览器窗口的一个接口
  3. 它是一个全局对象.定义在全局作用域中的变量、函数都会变成window对象的属性和方法
  4. 在调用window对象方法的时候,一般可以省略window
4.3 window对象常见事件
4.3.1窗口加载事件
  1. 使用

    window.onload = function () {
          
          }
    或
    window.addEventListener('load',function () {
          
          })
    
  2. 窗口加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、css文件等),就会调用该处理函数

  3. window.onload = function () {} 传统的注册事件只能写一次,以最后一个为准

  4. window.addEventListener(‘load’,function () {})没有限制

  5. 使用

    document.addEventListener('DOMContentLoaded',function () {
          
          
        alert('ll');
    })
    
    1. DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表,图片Flash等
    2. ie9以上才支持
    3. 应用场景
      1. 如果页面图片较多,从用户访问到onload触发可能需要较长的时间,交换效果不能实现,必然影响用户体验,此时可以用DOMContentLoaded事件比较合适
4.3.2 窗口大小调整
  1. 使用

    window.onresize = function () {
          
          };
    window.addEventListener('resize',function () {
          
          });
    
  2. 调整窗口大小加载事件,当触发时就调用处理函数

  3. 只要窗口大小发生像素变化,就会触发这个事件

  4. 使用场景

    1. 完成响应式布局,window.innerWidth获取当前屏幕宽度

      window.addEventListener('load',function () {
              
              
          var div = document.querySelector('div');
          window.addEventListener('resize',function () {
              
              
              if (window.innerWidth < 800) {
              
              
                  div.style.display = 'none';
              } else {
              
              
                  div.style.display = 'block';
              }
          })
      })
      
4.3.3 定时器
  1. setTimeout()定时器

    1. 用法

      window.setTimeout(调用函数(回调函数),[延迟的毫秒数]);
      
    2. 用于设置一个定时器,该定时器在定时器到期后执行调用函数

    3. 注意

      1. window可以省略
      2. 这个调用函数可以直接写函数,或者写函数名,或者采取字符串’函数名()'三种形式,第三种不推荐。
      3. 延迟的毫秒数省略默认为0
    4. 停止计时器

      1. window.clearTimeout(timer);
        
      2. window可以省略

      3. 取消先前通过调用setTimeout建立的定时器

      4. 里面的参数为定时器标识符,也即定时器的别名

      5. function closeBox() {
                  
                  
            var div = document.querySelector('div');
            div.style.display = 'none';
        }
        
        var timer = setTimeout(closeBox,5000);
        
        window.addEventListener('load',function () {
                  
                  
            var button = document.querySelector('button');
            button.addEventListener('click',function () {
                  
                  
                clearTimeout(timer);
            })
        })
        
  2. setInterval()定时器

    1. window.setInterval(调用函数(回调函数),[延迟的毫秒数]);
      
    2. 用法与setTimeout一样,主要区别是,该函数会每隔一定事件便调用回调函数,反复调用

    3. 停止定时器 clearInterval(timer);

4.3.4 this指向
  1. this最终指向的是那个调用它的对象
  2. 全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)
  3. 方法调用中谁调用this便指向谁
  4. 构造函数中this指向构造函数的实例
4.3.5 js执行机制
  1. js最大特点是单线程的,单线程意味着所有任务需要排队,这样会导致一个问题:如果js执行时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

  2. 为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker标准,允许javascript脚本创建多个线程,于是js出现了同步和异步。

  3. js执行将任务分为同步任务和异步任务

    1. 同步任务

      同步任务都在主线程上执行,形成一个执行栈

    2. 异步任务

      js的异步是通过回调函数实现的,分为以下三类

      1. 普通事件:click等
      2. 资源加载:onload等
      3. 定时器:setTimeout等
  4. js执行机制实现

    1. 先执行执行栈中的同步任务

    2. 异步任务(回调函数)放入任务队列中。

    3. 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行操作。

    4. js

    5. 由于主线程不断的重复获得任务、执行任务,再获得任务,再执行,这种机制被称为事件循环

  5. 用例分析

    console.log(1);
    document.onclick = function () {
          
          
        console.log('click');
    };
    console.log(2);
    setTimeout(function () {
          
          
        console.log(3);
    },3000);
    

    将上述js代码按照从上往下的次序放入执行栈中,如下图所示:

js_02

执行过程:

  1. 依次执行打印1,将onclick事件交由异步处理程序,打印2,将setTimeout事件交由异步处理程序

  2. 在setTimeout设置的3秒之前点击页面

    1. 异步进程在点击页面事件开始后,将处理函数(回调函数打印click)交由任务队列中

    2. 3秒之间完成之后,异步处理程序将回调函数(打印3)交由任务队列中

    3. 事件循环在主线程完成之后不断监听任务队列是否为空,不为空,将任务按照先进先出的原则将任务交由主线程进行执行

    4. 因此打印的结果如下:

    js_03

  3. 在setTimeout设置的3秒之后点击页面

    1. 3秒之间完成之后,异步处理程序将回调函数(打印3)交由任务队列中

    2. 异步进程在点击页面事件开始后,将处理函数(回调函数打印click)交由任务队列中

    3. 事件循环在主线程完成之后不断监听任务队列是否为空,不为空,将任务按照先进先出的原则将任务交由主线程进行执行

    4. 因此打印的结果如下:

    js_04

4.4 location对象
4.4.1 概述

window对象给我们提供了一个location属性用于获取或设置窗体的url,并且可以用于解析url,因为这个属性返回的是一个对象,因此也将这个属性称为location对象

4.4.2 location对象的属性
location对象属性 返回值
location.href 获取或者设置整个url
location.host 返回主机/域名
location.port 返回端口号
location.pathname 返回路径
location.serach 返回参数
location.hash 返回锚点
4.4.3 location对象方法
location对象方法 返回值
location.assign() 跟href一样,可以跳转页面(也称为重定向页面),记录历史,可以后退页面
location.replace() 替换当前页面,不记录历史,不可以后退页面
location.reload() 重新加载页面,相当于刷新按钮或者f5 如果参数为true 强制刷新CTRL+f5
4.4 navigator对象
  1. navigator对象包含有关浏览器的信息,很多属性,最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值

  2. 实现根据打开终端的不同跳转页面

    if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|ios|iPad|Android|Mobile|BlackBerry|IEMobile |MQQBrowser|JUC|Fennec|woSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
          
          
        window.location.href = "https://m.jd.com/";// 手机
    } else {
          
          
        window.location.href = "https://www.jd.com/";// 电脑
    }
    
4.4 history对象
  1. 与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL

  2. history对象方法 作用
    back() 后退
    forward() 前进
    go(参数) 前进/后退 参数是1 前进一个页面, -1 后退一个页面

猜你喜欢

转载自blog.csdn.net/chen__cheng/article/details/113773105