美文网首页Web 前端开发
DOM对象和类数组对象的探索

DOM对象和类数组对象的探索

作者: 夏知更 | 来源:发表于2018-07-17 19:14 被阅读1次

    实践是最好的老师,愿你的每一天都在学习中成长

    本文的主题是DOM对象和DOM数组,但是在正文开始之前,需要一点点铺垫

    在没有遇到这样的场景之前,我一直不清楚DOM对象和普通对象的区别,可是当我们遇见了需要处理的场景,就需要为了解决问题而做一些实践,深入了解一下其中的缘由。

    前言

    判断对象是否为空的方法
    • JSON.stringify()
    judgeEmptyObjectByJSON: function (obj) {
          return JSON.stringify(obj) === '{}';
     }
    
    console.log(judgeEmptyObjectByJSON({}));
    //true
    
    console.log(judgeEmptyObjectByJSON({name:'andy'}));
    //false
    
    
    • Object.keys()
    judgeEmptyObjectByObjectKeys: function (obj) {
    
        return Object.keys(obj).length === 0;
    }
    
    console.log(this.judgeEmptyObjectByObjectKeys({}));
    //true
    
    console.log(this.judgeEmptyObjectByObjectKeys({name:'andy'}));
    //false
    
    • $.isEmptyObject()
      在JQuery的源码中,isEmptyObject()函数时是这样写的:
      JQuery的源码isEmptyObject()

    原理是通过for...in遍历key

    judgeEmptyObjectByForIn: function (obj) {
    
          for(let name in obj){
            return false;
          }
    
          return true;
    }
    
    console.log(this.judgeEmptyObjectByForIn({}));
    //true
    
    console.log(this.judgeEmptyObjectByForIn({name:'andy'}));
    //false
    

    正文

    通过操作DOM元素拿到的Object和Array的特殊使用方法:

    关于Object
    • 场景
      在前端做上传文件,提交之前拿到和上传的文件有关的对象,按照需求对此对象进行判空处理。

    • 实践
      上传文件时,我们需要用到的基本html元素如下:

    <div class="main-content">
        <input type="file" class="input-file">
    </div>
    

    然后通过JQuery的选择器拿到相应的元素,为它绑定函数

     let fileInput = $('.input-file');
     fileInput.bind('change', this.updateFile);
    

    在updateFile()函数中取到和file有关的对象,它里面存着和上传的文件有关的信息:

    updateFile: function () {
          let file = $('.input-file');
          this.fileObject = file[0].files[0];
    
          console.log(this.fileObject);
          console.log(typeof this.fileObject);
     }
    

    然后在控制台看见打出的信息如图:


    file对象

    首先可以确定这是一个对象,而且对象中相关的字段都是肉眼可见,现在有需求描述:对此文件对象作判空处理,如果为空,则做其他处理。

    按照之前总结过的对象判空方法,我们先操作一下看结果:

    updateFile: function () {
          let file = $('.input-file');
          this.fileObject = file[0].files[0];
          
          console.log(this.fileObject);
          console.log(typeof this.fileObject);
    
          let isEmpty = JSON.stringify(this.fileObject) === '{}';
          console.log(isEmpty);
    },
    
    判断file对象是否为空
    好了,神奇的事情发生了,控制台告诉我们,此时的我们拿到的file对象是空的!!!
    很奇妙吧,当然一开始不知道是为什么,查了一些解决办法,也明白了一点:

    通过$()取出来的对象,是JQuery包装过的DOM对象,它的本质是和普通的数据对象是一致的

    但是,$(xxx)[0]就把JQuery对象转化成了DOM对象,一般对象的方法不适用于DOM对象

    所以,如果是通过操作DOM拿到的DOM对象,要先把他转化成JQuery对象,再使用对象的方法

    • 扩展:DOM对象转化的方法
      (1)、使用JQuery的$包裹对象;
    this.fileObject = $(this.fileObject);
    
    let isEmpty = JSON.stringify(this.fileObject) === '{}';
    console.log(isEmpty);    //false
    console.log(this.judgeEmptyObjectByObjectKeys(this.fileObject));     //false
    console.log(this.judgeEmptyObjectByForIn(this.fileObject));      //false
    

    (2)、使用JSON.stringify()时传入白名单

    let file = $('.input-file');
     this.fileObject = file[0].files[0];
    
    let isEmpty = JSON.stringify(this.fileObject,['lastModifiedDate','name','size','type','webkitRelativePath']) === '{}';
    console.log(isEmpty);      //false
    

    JSON.stringify(Object,[名单列表])

    • 遗留问题:
      此时的对象是DOM对象,其他的方法判断都是空的,但是JQuery的$.isEmptyObject()却可以正确判断,并且按理说DOM对象是不可以使用JQuery的方法的,但是现在几乎都不城里,不知原因为何?
    关于Array-Like(类数组)
    • 场景
      DOM元素通过ClassName或者TagName返回一个“数组”,希望对它进行操作。

    • 实践
      基本的html元素如下:

     <div>
          <div class="element">name</div>
          <div class="element">name</div>
          <div class="element">name</div>
          <div class="element">name</div>
          <div class="element">name</div>
     </div>
    

    通过操作dom拿到相应的数组对象:

    let domArray = document.getElementsByClassName('element');
    console.log(domArray);
    
    DOM数组对象

    判断类型:

    console.log(typeof domArray );    //object
    console.log(domArray instanceof Array);    //false
    

    此时,这个DOM数组的类型是对象,但又不是数组,只能称之为类数组对象
    在JS中,类数组对象是一个很特殊对象,它具有以下的特点:
    - 拥有length属性,其它属性(索引)为非负整数
    -不具有数组所具有的方法

    验证:

    console.log(domArray.slice(0,1));
    
    验证结果
    • 扩展:类数组对象转化为数组对象的方法
      为了方便操作类数组对象,使其能够使用数组对象的方法,我们需要将类数组对象转化为数组对象。
      (1)、Array.prototype.slice.call(arguments);
    let domArray = document.getElementsByClassName('element');
    let nodes = Array.prototype.slice.call(domArray);
    console.log(nodes instanceof Array);
    console.log(nodes.slice(0,1));
    
    转化结果
    (2)、Array.prototype.concat.apply([],arguments);
    let domArray = document.getElementsByClassName('element');
    let nodes = Array.prototype.concat.apply([],domArray);
    console.log(nodes instanceof Array);
    console.log(nodes.slice(0,1));
    
    转化结果
    (3)、Array.from(arguments);
    let domArray = document.getElementsByClassName('element');
    let nodes = Array.from(domArray);
    console.log(nodes instanceof Array);
    console.log(nodes.slice(0,1));
    
    转化结果

    (4)、 Object.values(obj)

    let domArray = document.getElementsByClassName('element');
    let nodes = Object.values(domArray);
    console.log(nodes instanceof Array);
    console.log(nodes.slice(0,1));
    
    转化结果
    (5)、 [...obj]
    let domArray = document.getElementsByClassName('element');
    let nodes = [...domArray];
    console.log(nodes instanceof Array);
    console.log(nodes.slice(0,1));
    
    转化结果

    结语

    这些JS中的细节,看见也没有在意过,但是在具体的问题面前,理解并解决问题也是很重要的。DOM对象是在需求中明确遇到了,类数组对象以前是没有见过的,有一天在社区看见一个人说出去面试遇到了这样的提问,问如何对类数组对象做迭代操作,但是实践中发现,类数组对象也是有length属性,可以通过for…in迭代的,当然也可以转化后再迭代。

    相关文章

      网友评论

        本文标题:DOM对象和类数组对象的探索

        本文链接:https://www.haomeiwen.com/subject/cqfipftx.html