javascript详解forin,Object.keys和Object.getOwnPropertyNames的区别

//详解forin,Object.keys和Object.getOwnPropertyNames的区别转自:http://it.taocms.org/05/7750.htm  

相关:http://yanhaijing.com/javascript/2015/05/08/member-of-object/

这三个方法,都可以用来遍历对象,这非常有用,其中后两个都是es5中新增的方法。

本文会用到一些es5的对象知识,如果你不了解,可以看一下开头提到的文章,首先我们需要一个父对象。

var parent = Object.create(Object.prototype, {
    a: {
        value: 1,
        writable: true,
        enumerable: true,
        configurable: true            
    }
});

parent继承自Object.prototype,有一个可枚举的属性a。下面我们在创建一个继承自parent的对象child。

var child = Object.create(parent, {
    b: {
        value: 2,
        writable: true,
        enumerable: true,
        configurable: true
    },
    c: {
        value: 3,
        writable: true,
        enumerable: false,
        configurable: true
    }
});

child有两个属性b和c,其中b为可枚举属性,c为不可枚举属性。

下面我们将用四种方法遍历child对象,来比较四种方法的不同。如下的代码代表程序的输出。

console.log('yanhaijing is God');
// > yanhaijing is God

:⑤代表es5中新增的方法,你可能需要一款现代浏览器来访问。

for in

for in是es3中就存在,最早用来遍历对象(集合)的方法。

for (var key in child) {
    console.log(key);
}
// > b
// > a

从输出可以看出,for in会输出自身以及原型链上可枚举的属性。

注意:不同的浏览器对for in属性输出的顺序可能不同。

如果仅想输出自身的属性可以借助 hasOwnProperty。可以过滤掉原型链上的属性。

for (var key in child) {
    if (child.hasOwnProperty(key)) {
        console.log(key);
    }
}
// > b

上面的代码,仅输出了child自己的可枚举属性b,而没有输出原型parent中的属性。

Object.keys⑤

Object.keyses5中新增的方法,用来获取对象自身可枚举的属性键。

console.log(Object.keys(child));
// > ["b"]

可以看出Object.keys的效果和for in+hasOwnProperty的效果是一样的。

Object.getOwnPropertyNames⑤

Object.getOwnPropertyNames也是es5中新增的方法,用来获取对象自身的全部属性名。

console.log(Object.getOwnPropertyNames(child));
// > ["b", "c"]

从输出可以看出其和Object.keys的区别。

总结

相信看完后,搞不清楚的同学应该明白了,在es3中,我们不能定义属性的枚举性,所以也不需要那么多方法,有了keys和getOwnPropertyNames后基本就用不到for in了。

如果你想在老旧浏览器中也是用这些方法,那试试es5shim吧。

Nodejs继承模块:merge-descriptors   utils-merge

/*!
 * merge-descriptors
 * Copyright(c) 2014 Jonathan Ong
 * Copyright(c) 2015 Douglas Christopher Wilson
 * MIT Licensed
 */

module.exports = merge

var hasOwnProperty = Object.prototype.hasOwnProperty


function merge(dest, src, redefine) {
  if (!dest) {
    throw new TypeError('argument dest is required')
  }

  if (!src) {
    throw new TypeError('argument src is required')
  }

  if (redefine === undefined) {
    // Default to true
    redefine = true
  }

  Object.getOwnPropertyNames(src).forEach(function forEachOwnPropertyName(name) {
    if (!redefine && hasOwnProperty.call(dest, name)) {
      // Skip desriptor
      return
    }

    // Copy descriptor
    var descriptor = Object.getOwnPropertyDescriptor(src, name)
    Object.defineProperty(dest, name, descriptor)
  })

  return dest
}

 

exports = module.exports = function(a, b){
  if (a && b) {
    for (var key in b) {
      a[key] = b[key];
    }
  }
  return a;
};

 

posted @ 2016-03-26 21:26  徐徐徐徐徐徐  阅读(2072)  评论(0编辑  收藏  举报