zoukankan      html  css  js  c++  java
  • 判断是否是纯粹的对象isPlainObject

    需求:
    有时候我想限定参事是一个对象,形如{a:1,b:2}类似于json格式。但是js中没有什么方法判断纯粹对象这个方法。
    js中一切都是对象,数字可以是Number对象,还有其他dom对象等等。typeof location,Object.toString.call(document)在ie下 都返回了object
    我们想要这样一个对象,他是个字面量,形如var o={a:1,b:2}.或者他是这样生成的var o=new Object();o.a=1;o.b=2;对于这样的构造函数为Object的对象o,才是满足我们要求的纯粹的对象。看下面jquery对纯粹对象的判断

    实现:
    jquery1.64中的

     1     isPlainObject: function( obj ) {
    2 // Must be an Object.
    3 // Because of IE, we also have to check the presence of the constructor property.
    4 // Make sure that DOM nodes and window objects don't pass through, as well
    5 //首先去除非对象,window对象,因为ie的dom返回的是object这里jquery的type函数不能去掉dom对象,只能去除一些带有nodeType的对象
    6 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
    7 return false;
    8 }
    9 //constructor属性是一个可以修改的值,这里通过constructor来判断是不靠谱的
    10 //如果是正常情况下,不修改constructor,这里先判断有constructor,
    11 //并且constructor不在对象自身里(一般情况下对象自身都不含constructor属性,constructor都在构造函数的prototype中定义)
    12 //再判断对象的构造函数的prototype中没有isPrototypeOf,只有构造函数是Object的情况下,才会拥有isPrototypeOf方法。
    13 //反过来说这里的判断逻辑是这样的,如果对象没有constructor属性,或者对象的constructor是自身的属性(对象只能是构造函数的prototype),或者对象的构造函数是Object的情况
    14 try {
    15 // Not own constructor property must be Object
    16 if ( obj.constructor &&
    17 !hasOwn.call(obj, "constructor") &&
    18 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
    19 return false;
    20 }
    21 } catch ( e ) {
    22 // IE8,9 Will throw exceptions on certain host objects #9897
    23 return false;
    24 }
    25
    26 // Own properties are enumerated firstly, so to speed up,
    27 // if last one is own, then all properties are own.
    28 //for in 枚举了obj的所有属性。ff系列会首先枚举自身的属性,但是ie系列并不是。所以下面的通过最后一个属性来判断并不对啊
    29 var key;
    30 for ( key in obj ) {}
    31
    32 return key === undefined || hasOwn.call( obj, key );
    33 },

    行6中。因为ie的问题,并不能去除一些dom,比如location。不过可以限制Object
    行14中。因为constructor的可变性,判断不靠谱.不过正常情况下,一般不会手动修改constructor
    行29中。for in遍历就是个错误,ff下可行,ie下根本就不对。

    淘宝kissy中的实现

     1             isPlainObject:function (o) {
    2 /**
    3 * note by yiminghe
    4 * isPlainObject(node=document.getElementById("xx")) -> false
    5 * toString.call(node) : ie678 == '[object Object]',other =='[object HTMLElement]'
    6 * 'isPrototypeOf' in node : ie678 === false ,other === true
    7 * refer http://lifesinger.org/blog/2010/12/thinking-of-isplainobject/
    8 */
    9 return o && toString.call(o) === '[object Object]' && 'isPrototypeOf' in o;
    10 },

    这个实现过于简单了。这里如果是new function(){}的对象,这里可以通过


    Qwrap中的实现

     1     function getConstructorName(o) { 
    2 //加o.constructor是因为IE下的window和document
    3 if(o != null && o.constructor != null){
    4 return Object.prototype.toString.call(o).slice(8, -1);
    5 }else{
    6 return '';
    7 }
    8 }
    9 isPlainObject: function(obj) {
    10 return getConstructorName(obj) == 'Object';
    11 },

    这里的实现也有问题。从这里看出一般的框架中都没有给出一个完美的实现方法。

    总结
    综上看来,jquery实现的其实还是考虑比较全面的。但是因为js语言本身没有什么办法判断,所以只能约定好多写注释。
    不过我们也可以总结下已有的判断方式如下
    1通过constructor和isPrototypeOf判断。
      constructor必须是Object,且isPrototypeOf是.constructor的ownProperty。
    2通过for in遍历来判断。
      这个是最靠谱但是又最影响性能的判断
      通过遍历出所有属性,判断是否是ownProperty
      





  • 相关阅读:
    AES-GCM算法
    Linux Curl命令
    OpenLDAP
    网络性能测试
    LoadRunner
    XSLT
    dtruss
    删除重复图片
    2018年部门管理的一点总结
    矢量地图方案的进一步探讨
  • 原文地址:https://www.cnblogs.com/lunalord/p/2389695.html
Copyright © 2011-2022 走看看