美文网首页程序员让前端飞
JavaScript 对象属性的存在性

JavaScript 对象属性的存在性

作者: 打铁大师 | 来源:发表于2018-09-06 23:27 被阅读4次

    先看一个例子

    var person = {
      name:undefined
    }
    console.log(person.name); // undefined
    console.log(person.age); // undefined
    

    上面的例子中 person对象有一个name属性,没有age属性。但是,使用
    person.name 和 person.age访问属性值时,两者的结果都是undefined。

    因此我们没法通过值为undefined来判断一个对象是否有某个属性。

    那么如何判断一个对象是否存在一个属性。

    1. in 操作符

    如果指定的属性存在对象或其原型链中,那么in操作符返回true 。

    注意: in操作符判断属性的存在性,不论属性是否可枚举

    举个例子:

    let man = {
      speak: 'I can'
    }
    
    // 已man对象为原型创建person对象
    let person = Object.create(man);
    //定义person对象的name属性,该属性是person对象的自有属性
    person.name='noshower';
    
    //定义person对象的自有属性,但是'age'不可枚举,
    Object.defineProperty(person, 'age', {
      enumerable: false,
      configurable: true,
      writable: true,
      value: 23
    });
    
    console.log('speak' in person);  // true
    console.log('name' in person);   // true
    console.log('age' in person);   // true
    console.log('job' in person);   // false
    

    因为job不存在person中,也不存在person对象的原型链上,所以结果为false。

    再看个例子:

    var array = new Array('a','b','c','d','e');
    delete array[3];
    console.log(3 in array); // false
    console.log(array.length); // 5
    

    从这个例子中看出,当删除数组的某个下标后,数组下标确实不存在了。但是没有改变数组的长度。只是该位置被空出来了而已。

    2. hasOwnProperty

    如果对象自身属性中存在指定的属性,那么hasOwnProperty()方法将会返回true,否则返回false。

    注意:

    • hasOwnProperty 不会检查对象原型链上的属性。

    • hasOwnProperty 不论属性是否可以枚举

    • hasOwnProperty方法存在于Object.prototype上,因此只要对象的原型链上存在Object.prototype, 就可以直接访问hasOwnProperty方法。有点对象(通过Object.create(null)创建的对象)没有连接到Object.prototype,那么就无法访问到hasOwnProperty方法。

    • JavaScript 没有保护hasOwnProperty属性名,因此,任何对象都可以使用hasOwnProperty这个名字作为属性名。

    • 上述两点,所以可必要使用Object.prototype.hasOwnProperty.call(obj,prop)这种形式判断某个属性的存在, 这样就无需担心obj上是否存在hasOwnProperty方法或者hasOwnProperty被覆盖的问题。

    举个例子:

    let man = {
      speak: 'I can'
    }
    
    let person = Object.create(man);
    
    person.name='noshower';
    
    Object.defineProperty(person, 'age', {
      enumerable: false,
      configurable: true,
      writable: true,
      value: 23
    });
    
    console.log(person.hasOwnProperty('speak')); // false
    console.log(person.hasOwnProperty('name')); // true
    console.log(person.hasOwnProperty('age')); // true
    console.log(person.hasOwnProperty('job')); // false
    

    因为speak属性存在于原型链上,所以返回false。
    因为name属性是自有属性,所以返回true。
    因为age属性是自有属性,虽然该属性不可枚举,但结果还是true。
    因为job属性不存在,所以没有false。

    3. for...in 循环

    for...in 循环用来遍历对象的可枚举属性,包括原型链上的

    注意:

    • for..in 循环以任意顺序迭代一个对象的属性,不同浏览器遍历属性的顺序可能不同。 因此,最好不要在迭代中对对象进行添加、修改或删除属性。

    • 不要使用for..in遍历数组

    • for...in不会返回不可枚举的属性

    举个例子:

    let man = {
      speak: 'I can'
    }
    
    let person = Object.create(man);
    
    person.name='noshower';
    
    Object.defineProperty(person, 'age', {
      enumerable: false,
      configurable: true,
      writable: true,
      value: 23
    });
    
    for(let prop in person){
      console.log(prop);   // name , speak (并不一定是这样的输出顺序)
    }
    

    其中age属性没有遍历得到,因为它是不可枚举的。

    4. propertyIsEnumerable

    如果一个属性是对象的自有属性(直接定义在对象上的)且该属性可枚举,那么 propertyIsEnumerable方法返回true,否则返回false。

    举个例子:

    let man = {
      speak: 'I can'
    }
    
    let person = Object.create(man);
    
    person.name='noshower';
    
    Object.defineProperty(person, 'age', {
      enumerable: false,
      configurable: true,
      writable: true,
      value: 23
    });
    
    console.log(person.propertyIsEnumerable('speak')); //false
    console.log(person.propertyIsEnumerable('name')); // true
    console.log(person.propertyIsEnumerable('age')); // false
    

    5. Object.keys()

    Object.keys() 方法会返回一个由给定对象的所有自身可枚举属性组成的数组。

    注意:

    • Object.keys() 返回的属性是可枚举

    • Object.keys()返回的属性是对象的自有属性

    • 结果数组中属性名的排列顺序和使用 for ...in循环遍历该对象时返回的顺序一致

    举个例子:

    let man = {
      speak: 'I can'
    }
    
    let person = Object.create(man);
    
    person.name='noshower';
    
    Object.defineProperty(person, 'age', {
      enumerable: false,
      configurable: true,
      writable: true,
      value: 23
    });
    
    console.log(Object.keys(person)); // [ 'name' ]
    

    6. Object.getOwnPropertyNames()

    Object.getOwnPropertyNames()方法会返回一个数组,包含所有自有属性,无论它们是否可枚举。

    注意:

    • 返回的是自有属性
    • 不论是否可枚举
    • 不包括Symbol值作为名称的属性
    • 数组中可枚举属性的顺序与通过for...in循环(或Object.keys)迭代该对象属性时一致。数组中不可枚举属性的属性未定义。

    举个例子:

    let man = {
      speak: 'I can'
    }
    
    let person = Object.create(man);
    
    person.name='noshower';
    
    Object.defineProperty(person, 'age', {
      enumerable: false,
      configurable: true,
      writable: true,
      value: 23
    });
    
    console.log(Object.getOwnPropertyNames(person)); //[ 'name', 'age' ]
    

    7.自定义函数:getOwnInnumerablePropertyNames

    getOwnInnumerablePropertyNames 只获取对象自身的所有不可枚举属性

    function getOwnInnumerablePropertyNames (obj){
        //返回对象的所有自有属性,包括不可枚举的
        let props = Object.getOwnPropertyNames(obj);
        //返回对象的所有可枚举属性
        let propsEnum = Object.keys(obj); 
        // 过滤出所有不可枚举的
        return props.filter(function(key){
          return propsEnum.indexOf(key) === -1;
        })
    }
    

    参考文献

    • 《你不知道的JavaScript 上卷》

    • MDN

    相关文章

      网友评论

        本文标题:JavaScript 对象属性的存在性

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