第四周

62 阅读12分钟
  • Object面向对象\

    • 继承
      父对象的成员(属性和方法),子对象可以直接使用

      • 为什么
        代码重用,节约内存空间
      • 何时
        只要多个子对象公用的属性和方法都要集中定义在父对象之中
    • JS的面向对象是基于原型(父亲)的\

      • 原型:保存一类子对象共有属性和方法的父对象(原型对象),每个对象天生有一个原型\
      • 获取原型对象\

        • 对象名.proto;
          必须先创建出一个对象,才可以使用
        • 构造函数名.prototype;
          构造函数名:Array、Function、Date、RegExp - 哪怕没有创建对象也能找到原型
      • 两链一包\

        • 作用域链\

          • 一函数EC的scope chain属性为启迪那,经过AO逐级引用,形成从一条链式结构\
          • 作用:查找变量的,带来了变量的使用规则;优先使用自己的,自己没有找到全局对象\
        • 闭包\

          • 保护了一个可以反复使用的局部变量的词法结构\
        • 原型链\

          • 每个对象都有一个.__proto__的属性,可以不断的连续找到爸爸-爷爷...形成的一条链式结构\
          • 经过尝试,发现最顶层Object.prototype是对象的原型,即“万物皆对象”\
          • 作用:查找属性和方法,自己没有的属性和对象,可以自动顺着原型链进行查找\
      • 获取到原型对象则可以设置共有属性和共有方法
        原型对象.属性名=属性值;//共有属性
        原型对象.方法名=function; //共有方法\

        • 自有和共有\

          • 自有:保存在对象本地的属性\
          • 共有:保存在父(原型)对象的属性,所有的子对象都可以使用\
        • 笔试题\

          • 1、如何判断自有和共有\

            • 判断自有:obj.hasOwnProperty(“属性名”)
              返回一个布尔值:true说明是自有,false说明可能是共有也有可能是没有
            • 判断共有:2个条件\

              • 不是自有:obj.hasOwnProperty(“属性名”)\
              • 自动在原型链检查:"属性名"in 对象名
                if(obj.hasOwnProperty("属性名")==false&&"属性名"in 对象名){//共有}
                完整版:
                if(obj.hasOwnProperty("属性名")){
                console.log("自有");
                }else{
                if("属性名" in 对象名){
                console.log("共有")
                }else{
                console.log("没有")
                }
                }\
          • 2、修改或删除属性\

            • 自有\

              • 修改:obj.属性名=新值\
              • 删除:delete obj.属性名\
            • 共有\

              • 修改:原型对象.属性名=新值\
              • 删除:delete原型对象.属性名\
          • 3、为老IE的数组添加indexOf方法 - 这道题不是固定的:为某一类人设置一个方法
            if(Array.prototype.indexOf===undefined){//我不希望主流浏览器也执行到这些代码,我只希望老IE执行到
            Array.prototype.indexOf=function(key,starti){//indexOf的执行原理
            starti===undefined&&(starti=0);//说明用户没有传入开始位置,我们就给用户设置为从下标0开始查找
            for(var i=starti;i
            if(this[i]==key){
            return i;//匹配到了返回对应的下标
            }
            }
            //没匹配到,返回-1
            return -1;
            }
            }
          • 4、判断x是不是数组(4种方法)\

            • a.判断x是不是继承自Array.prototype
              Array.prototype.isPrototypeOf(x);
              ​如果返回true,说明是数组,否则不是数组
            • b.判断是否是由构造函数Array创建的
              x instanceof Array
            • ES5提供的API:Array.isArray(x)(老IE不支持)\
            • 输出对象的字符串形式
              Object的prototype原型上放着最原始的toString,原始的toString,默认输出[object 构造函数名]

              • 多态(override)/重写
                子对象绝对父对象的成员不好用,可以在本地定义同名成员,覆盖父对象之中的成员

                • Object.prototype.toString.apply(x)==="[object Array]";\
          • 实现自定义继承\

            • 实现两个对象之间的基础\

              • 子对象.proto=父对象;\
            • 直接匹配设置继承\

              • 构造函数名.prototype=父对象;
                先设置好父对象,再创建子对象
  • ES5
    在ES3的基础添加了一些新特性、新语法、新API---简化ES3

  • 1、保护对象
    保护对象的属性和方法

    • 1、四大特性
      每个属性都有四大特性


      • {
        "value": 3500, //实际保存属性值的地方
        "writable": true,//开关:控制着是否可以被修改
        "enumerable": true,//开关:控制着是否可以被for in循环遍历到
        "configurable": true//开关:控制着是否可以被删除
        }\
      • 修改四大特性
        object.defineProperties(obj,{
        "属性名":{四大特性}
        ​})
    • 2、三个级别\

      • 防扩展
        禁止给对象添加任何新属性

        • object.preventExtensions(obj);\
      • 密封
        禁止给对象添加任何新属性,也不能删除属性

        • object.seal(obj);\
      • 冻结
        禁止给对象添加任何新属性,也不能删除属性,也不能修改属性

        • object.freeze(obj);\
  • 数组的新API\

    • 1、判断\

      • every
        每一个:判断数组中的每个元素都要复合要求最后结果才为true,类似&&

        • 语法
          var bool=arr.every(function(val,i,arr){
          console.log(val);//当前元素
          console.log(i);//当前元素的下标
          console.log(arr);//数组本身
          return 判断条件;
          })
      • some
        有一些:判断数组中的是否包含复合要求的元素,只要有一个最后结果则为true,类似||,只要有一个满足,则为true,只有全都不满足,结果才为false结果

        • 语法
          var bool=arr.some(function(val,i,arr){
          return 判断条件;
          })\
    • 2、遍历
      对每个元素执行相同 或 相似的操作

      • forEach
        直接修改原数组

        • 语法
          arr.forEach(function(val,i,arr){
          操作;
          ​})
      • map
        不修改原数组,返回新数组

        • 语法
          var newArr=arr.map(function(val,i,arr){
          return 操作;
          ​})
    • 3、过滤和汇总\

      • 过滤
        筛选出原数组之中符合条件的元素组成一个新数组,原数组不变

        • 语法
          var newArr=arr.filter(function(val,i,arr)){return 判断条件;})
      • 汇总
        将数组中每一个元素,取出来整合为一个最终结果

        • 语法
          var sum=arr.reduce(function(prev,val,i,arr){
          return prev+val;
          ​},基础值)
  • Object.create()方法
    直接用父对象创建子对象,并且子对象扩展自有属性

    • 语法
      var 子对象=Object.create(父对象,{
      "自有属性":{四大特性},
      ...
      ​}
  • 严格模式:很严格(最好不用)
    用"use strict";开启

    • 禁止给未声明的对象赋值---解决了全局污染\
    • 将静默失败升级为错误\
  • call,aplly,bind\

    • 1、call,apply:临时替换函数中的this,借用\

      • 差别\

        • call要求传入函数的实参必须单独传入\
        • apply要求传入函数的实参必须是一个数组\
      • 语法\

        • 要借用的函数.call(借用的对象,实参1,...);\
        • 要借用的函数.apply(借用的对象,arr);\
    • 2、bind
      永久替换函数中的this,买

      • 语法
        var 新函数=老函数.bind(指定的对象)
      • 3件事\

        • 1、创建了一个和原函数功能完全一样的新函数\
        • 2、将新函数中的this永久绑定为你指定的对象\
        • 3、将新函数中的步伐参数永久固定\
      • 强调\

        • bind绑定在新函数中的this,无法被call、apply再次替换节奏\
    • 总结:\

      • 如果临时调用一个函数,立刻执行时---call/apply\
      • 如果创建一个饿汉式提前绑定this,不一定希望理科执行---bind\
    • 使用场景\

      • 比较出数组中的最大值和最小值
        Math.max/min.apply(Math,arr);
      • 得到Object最原始的toString
        Object.prototype.toString.call/apply(arr);
      • 将类数组对象转为普通数组
        var 新数组=Array.prototype.slice.call/apply(类数组对象);

        • ES5还提供了一个数组API,可以直接将类数组对象转为普通数组:var 新数组=Array.from(类数组对象)\
  • ES6新语法\

    • 1、模板字符串
      在字符串中实现了一个简单的js环境

      • 语法
        我的名字是${name}
    • 2、let关键字
      创建变量以后优先使用let,再考虑var

      • 语法
        let 变量名=值
      • 优点\

        • 1、解决了声明提前\
        • 2、添加了块级作用域,一个{}就是一个块\
        • 3、如果绑定事件时,用到了let来遍历,那么let会记录住你当前元素的下标 - 你以后再也不需要自定义下标了\
    • 3、箭头函数
      简化一切的回调函数

      • 去掉function,()和{}之间添加=>,形参只有一个的话可以省略\
      • 函数体只有一句话==>省略{}\
      • 含糊提只有一句话,并且是return==>省略{}和return\
    • 4、for...of(不好用)\

      • 语法
        for(var v of arr){
        v- 直接拿到值
        ​}
      • 1、不能修改原数组\
      • 2、不能遍历hash数组和对象\
  • 1、DOM
    document Object Model(文档对象模型)

    • 面试题\

      • HTML/XHTML/DHTML/XML分别是什么\

        • 1、HTML--网页\
        • 2、XHTML--更严格的HTML,HTML5--XHTML--HTML4.01\
        • 3、DHTML--动态网页,D:Dynamic--将现有计算的整合统称,让我们离线时也具有动态效果
          DHTML:html+css+js(dom)
        • 4、XML--未知的标记语言,一切标记由自己定义,数据格式\
    • DOM为了方便各类开发者,分为了3部分\

      • 1、核心DOM\

        • 既可以操作HTML,又可以操作XML\
        • 缺点:API比较繁琐\
      • 2、HTML DOM\

        • 只能操作HTML,API简单\
        • 缺点:比如属性部分,只能访问标准属性,不能访问自定义属性\
      • 3、XML DOM\

        • 只能操作XML,但XML已经淘汰了,现在最流行的数据格式是JSON\
      • 开发建议:有限HTML DOM,HTML DOM实现不了再用核心DOM进行补充\
  • 2、DOM树\

    • 树根:document
      不需要我们创建,一个页面只有一个document对象,由浏览器的js解释器自动创建
    • 作用\

      • 可以通过树根找到页面上的每一个DOM元素/节点/对象,也可以操作它\
  • 3、每个DOM元素都有三大属性\

    • 1.elem.nodeType
      描述节点的类型,现在不用,直接方法children

      • document节点:9\
      • element节点:1\
      • attribute节点:2\
      • text节点:3\
    • 2.attrNode.nodeValue
      描述节点的值

      • 以前有用,先拿到属性节点,再用属性获取属性值\
    • 3.elem.nodeName
      描述节点的名字

      • 拿到当前元素的标签名,判断是什么标签\
      • 返回的是一个全大写组成的标签名\
  • 通过关系过去元素\

    • 父:xx.parentNode\
    • 子:xx.children------是集合,只能找到儿子\
    • 第一个儿子:xx.firstElementChild\
    • 最后一个儿子:xx.lastElementChild\
    • 前一个兄弟:xx.previousElementSling\
    • 后一个兄弟:xx.nextElementSibling\
  • ***** 递归
    简单来说就是函数中又一次调用量函数自己,迟早有一天会停下来

    • 何时使用
      遍历DOM树,专门用于遍历层级不明确的情况,既可以遍历层级不明确的DOM树,也可以遍历层级不明确的数据
    • 如何使用(2步)
      function 函数名(root){
      1、第一层要做什么直接做
      2、判断有没有下一级,如果有,再次调用此函数,但是传入的实参是他的下一级
      ​}
      函数名(实际的根)
    • 算法\

      • 深度优先!优先遍历当前系统的子节点,子节点遍历完才会跳到兄弟节点\
    • 缺点\

      • 同时开启大量的函数调用,大量消耗内存,只有遍历层级不明确的时候使用\
    • 递归和循环对比\

      • 递归\

        • 优点:直观、易用\
        • 缺点:性能较低,尽量只在层级不明确的时候使用\
      • 循环\

        • 优点:几乎不占用内存\
        • 缺点:太难\
  • 6、TreeWalker
    在DOM树上行走的遍历层级不明确的DOM树的API

    • 1、创建tw
      var tw=document.createTreeWalker(根元素,NodeFilter.SHOW_ALL/SHOW_ELEMENT);
    • 2、tw对象过后,会得到一个方法,反复调用nextNode方法找到下一个节点,迟早有一天会等于null,说明没找到
      while((node=tw.nextNode())!=null){
      node要干什么
      }\

      • 缺点\

        • 自动的跳过根元素,根元素是不会做任何操作的\
        • 仅仅只能遍历层级不明确的DOM树,不能遍历层级不明确的数据\
  • 7、API直接找元素\

    • 1、根据HTML的特点找元素\

      • ID:var elem=document.getElementById("id值");\
        • 标签名和* class和name:var elems=document.getElementsByTagName/ClassName/Name("标签名/class名");\
    • 2、根据CSS选择器找元素\

      • 1、单个元素
        var elem=document.queryselector("任意的css选择器");

        • 强调:万一选择器匹配到多个,只会返回第一个\
      • 2、多个元素
        var elem=document.querySelectorAll("任意的css选择器");

        • 强调:找到了返回集合,没找到返回空集合,更适合做复杂查找\
    • 面试题/笔试题:getXXX和querySelectorAll有什么区别\

      • 返回结果不同\

        • 1、getXXX:返回的是要给动态集合HTMLCollection\

          • 优点:数据始终和DOM树实时挂钩\
          • 缺点:每次DOM树进行修改,都会悄悄的再次查找元素,效率相对较低\
        • 2、querySelectorAll:返回的是要给静态集合NodeList\

          • 优点:每次不会悄悄重新查找,效率较高,而且还支持使用forEach!\
  • DOM\

    • 元素的内容\

      • elem.innerHTML
        获取或设置开始标签到结束标签之间的HTML代码,没有兼容性问题的可以识别标签

        • 获取:elem.innerHTML\
        • 设置:elem.innerHTML="新内容"\
      • elem.textContent
        获取或设置开始标签到结束标签之间的纯文本,有兼容性问题的(老IE不支持),不能识别标签

        • 获取:elem.textContent\
        • 设置:elem.textContent="新内容"\
        • 老IE:elem.innerText;\

          • 为什么老IE不讲究主流?
            微软的,生活中,PC端只有 windows系统 和 MAC系统(土豪),windows系统的使用的人多
      • input.value
        获取或设置表单控件的值 - 只要你做正则验证

        • 获取:input.value\
        • 设置:input.value="新值"\
    • 元素的属性\

      • 获取属性值\

        • 核心DOM:elem.getAttribute("属性名");\
        • HTML DOM:elem.属性名\
      • 设置属性值\

        • 核心DOM:elem.setAttribute("属性名","属性值");\
        • HTML DOM:elem.属性名="属性值";\
      • 删除属性值\

        • 核心DOM:elem.removeAttribute("属性名");\
        • HTML DOM:elem.属性名=""
          删除不推荐使用HTML DOM,删除不干净属性节点,而有的属性,光有属性名就已经具有功能了
      • 判断有没有属性\

        • 核心DOM:elem.hasAttribute("属性名")
          仅仅只能判断有没有这个属性,不能判断出属性值是什么,往往我们自己用获取属性值的操作,获取到了过后再去进行比较运算
        • HTML DOM:elem.属性名!="";\
      • HTML DOM缺陷\

        • 1、class需要写为className\
        • 2、不能操作自定义属性\
    • 元素的样式\
  • DOM3\

    • 1、创建元素并渲染DOM树(3步)\

      • 1、创建空标签\

        • var elem=document.createElement("标签名")\
      • 2、添加必要的属性和事件\

        • elem.属性名="属性值"\
        • elem.on事件=function(){}\
      • 3、上树:将js内存中的新标签放到DOM树上\
    • 2、删除元素\
  • HTML DOM常用对象:简化【核心DOM】\

    • 1、image对象
      仅仅是简化了创建语句

      • 创建:var img=new Image();
        var elem=document.createElement("img");
      • 注意:不是人人都有构造函数创建方式\
    • 2、form对象
      简化了查找元素

      • 查找form元素:var form=document.forms[i];\
      • 查找form元素中的表单控件:var inp=form.elements[i];\
      • 专属事件\