for..in循环

使用for..in循环时,返回的是所有能够通过对象访问的、可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例。这里需要注意的是使用for-in返回的属性因各个浏览器厂商遵循的标准不一致导致对象属性遍历的顺序有可能不是当初构建时的顺序。

虽然for..in主要用于遍历对象的属性,但同样也可以用来遍历数组元素。

var arr = ['a', 'b', 'c', 'd'];

// 使用for..in
for (var i in arr) {
console.log('索引:' + i + ',值:' + arr[i]);
} // 使用for循环
for (var j = 0; j < arr.length; j++) {
console.log('索引:' + j + ',值:' + arr[j]);
} /* 两种方式都输出:
* ----------------
* 索引:0,值:a
* 索引:1,值:b
* 索引:2,值:c
* 索引:3,值:d
* ----------------
*/

如何查看一个属性的特性可以使用propertyIsEnumberable()Object.getOwnPropertyDescriptor()这两个方法。

var colors = ['red', 'green', 'blue'];
// 扩展Array.prototype
Array.prototype.demo = function () {}; for (var i in colors) {
console.log(i); // 输出: 0 1 2 demo
} // 查看原生的方法[[enumberable]]特征,这里以splice为例
Array.prototype.propertyIsEnumerable('splice'); // false
Object.getOwnPropertyDescriptor(Array.prototype, 'splice'); // {writable: true, enumerable: false, configurable: true} // 查看 demo 属性的特性
Array.prototype.propertyIsEnumerable('demo'); // true
Object.getOwnPropertyDescriptor(Array.prototype, 'demo'); // {writable: true, enumerable: true, configurable: true}

从上面的示例代码中可以看出,我们添加的demo方法,默认是可以被for..in枚举出来的。如果想让其不被枚举,那么可以使用ES5的Object.defineProperty()来定义属性,此外如果浏览器版本不支持ES5的话,我们可以使用hasOwnProperty()方法在for..in代码块内将可枚举的属性过滤掉。

var colors = ['red', 'green', 'blue'];
Object.defineProperty(Array.prototype, 'demo', {
enumerable: false,
value: function() {}
}); Array.prototype.propertyIsEnumerable('demo'); // false
Object.getOwnPropertyDescriptor(Array.prototype, 'demo'); // {writable: false, enumerable: false, configurable: false} for (var i in colors) {
console.log(i); // 输出:0 1 2
} // 或者使用 hasOwnProperty
var colors = ['red', 'green', 'blue'];
Array.prototype.demo = function() {}; // 安全使用hasOwnProperty方法
var hasOwn = Object.prototype.hasOwnProperty;
for (var i in colors) {
if (hasOwn.call(colors, i)) {
console.log(i); // 输出:0 1 2
}
}

Object.keys()

Object.keys()用于获取对象自身所有的可枚举的属性值,但不包括原型中的属性,然后返回一个由属性名组成的数组。注意它同for..in一样不能保证属性按对象原来的顺序输出。

// 遍历数组
var colors = ['red', 'green', 'blue'];
colors.length = 10;
colors.push('yellow');
Array.prototype.demo = function () {}; Object.keys(colors); // 0 1 2 10 // 遍历对象
function Person(name, age) {
this.name = name;
this.age = age;
} Person.prototype.demo = function() {}; var jenemy = new Person('jenemy', 25); Object.keys(jenemy); // name age

注意在 ES5 环境,如果传入的参数不是一个对象,而是一个字符串,那么它会报 TypeError。在 ES6 环境,如果传入的是一个非对象参数,内部会对参数作一次强制对象转换,如果转换不成功会抛出 TypeError。

// 在 ES5 环境
Object.keys('foo'); // TypeError: "foo" is not an object // 在 ES6 环境
Object.keys('foo'); // ["0", "1", "2"] // 传入 null 对象
Object.keys(null); // Uncaught TypeError: Cannot convert undefined or null to object // 传入 undefined
Object.keys(undefined); // Uncaught TypeError: Cannot convert undefined or null to object

由于Object.keys()为ES5上的方法,因此对于ES5以下的环境需要进行polyfill

// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
if (!Object.keys) {
Object.keys = (function() {
'use strict';
var hasOwn = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length; return function(obj) {
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
throw new TypeError('Object.keys called on non-object');
} var result = [], prop, i; for (prop in obj) {
if (hasOwn.call(obj, prop)) {
result.push(prop);
}
} if (hasDontEnumBug) {
for (i = 0; i < dontEnumsLength; i++) {
if (hasOwn.call(obj, dontEnums[i])) {
result.push(dontEnums[i]);
}
}
}
return result;
}
}) ();
}

Object.getOwnPropertyNames()

Object.getOwnPropertyNames()方法返回对象的所有自身属性的属性名(包括不可枚举的属性)组成的数组,但不会获取原型链上的属性。

function A(a,aa) {
this.a = a;
this.aa = aa;
this.getA = function() {
return this.a;
}
}
// 原型方法
A.prototype.aaa = function () {}; var B = new A('b', 'bb');
B.myMethodA = function() {};
// 不可枚举方法
Object.defineProperty(B, 'myMethodB', {
enumerable: false,
value: function() {}
}); Object.getOwnPropertyNames(B); // ["a", "aa", "getA", "myMethodA", "myMethodB"]

参考地址:https://www.cnblogs.com/wujie520303/p/4931384.html

小tips:JS之for in、Object.keys()和Object.getOwnPropertyNames()的区别的更多相关文章

  1. js 遍历对象属性(for in、Object.keys、Object.getOwnProperty) 以及高效地输出 js 数组

    js中几种遍历对象的方法,包括for in.Object.keys.Object.getOwnProperty,它们在使用场景方面各有不同. for in 主要用于遍历对象的可枚举属性,包括自有属性. ...

  2. JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  3. 遍历对象属性(for in、Object.keys、Object.getOwnProperty)

    js中几种遍历对象的方法,包括for in.Object.keys.Object.getOwnProperty,它们在使用场景方面各有不同. for in 主要用于遍历对象的可枚举属性,包括自有属性. ...

  4. [转] JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别

    ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...

  5. 关于Object.keys()和for in的区别

    今天见到一道面试题让说一说Object.keys()和for in的区别,顿时有些发懵“What's Object.keys?”我立马上网搜了一下,大致作用也是做遍历,参数是一个对象,返回值是一个数组 ...

  6. or in 、Object.keys()以及Object.getOwnPropertyNames有什么区别?

    or in .Object.keys()以及Object.getOwnPropertyNames的区别 var obj= Object.create(parent, { b: { value: 2, ...

  7. 关于Object.keys()和Object.values()的使用

    关于Object.keys()和Object.values()的使用 1. 关于Object.keys() 1) 处理对象,返回可枚举的所有可枚举属性的字符串数组 let person ={ name ...

  8. js 对象与数组相互转化的快捷方法 Object.keys()、Object.values()、Object.entries()

    Object.keys() Object.keys 返回一个所有元素为字符串的数组,其元素来自于从给定的object上面可直接枚举的属性.这些属性的顺序与手动遍历该对象属性时的一致. 例如: let ...

  9. Object.keys(),Object.values() 用法

    ES8新特性 Object.keys() 用法 返回键名组成的数组, let arr={ name:'js', sex:'body' } let keys=Object.keys(arr); cons ...

随机推荐

  1. [译文]Domain Driven Design Reference(七)—— 大型战略设计结构

    本书是Eric Evans对他自己写的<领域驱动设计-软件核心复杂性应对之道>的一本字典式的参考书,可用于快速查找<领域驱动设计>中的诸多概念及其简明解释. 上周末电脑硬盘文件 ...

  2. WPF:How to display a Bitmap on Image control

    一个Bitmap文件,叫做screenShotFile, 你可以这样显示到Image控件上. BitmapImage bi = new BitmapImage();            bi.Beg ...

  3. RabbitMQ CLI 管理工具 rabbitmqadmin(管理和监控)

    插个广告,公司最近在招".NET"开发(杭州),如果你现在还从事 .NET 开发(想用 .NET Core,但被公司不认可),想转 JAVA 开发(但又没有工作经验,惧怕面试),想 ...

  4. CSS Media媒体查询使用大全,完整媒体查询总结

    前面的话 一说到响应式设计,肯定离不开媒体查询media.一般认为媒体查询是CSS3的新增内容,实际上CSS2已经存在了,CSS3新增了媒体属性和使用场景(IE8-浏览器不支持).本文将详细介绍媒体查 ...

  5. [Swift]LeetCode1009. 十进制整数的补码 | Complement of Base 10 Integer

    Every non-negative integer N has a binary representation.  For example, 5 can be represented as &quo ...

  6. 机器学习入门15 - 训练神经网络 (Training Neural Networks)

    原文链接:https://developers.google.com/machine-learning/crash-course/training-neural-networks/ 反向传播算法是最常 ...

  7. webpack的基本配置项

    const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin& ...

  8. Java连接数据库之MySQL

    工具: eclipse MySQL Navicat for MySQL MySQL 连接驱动:mysql-connector-java-5.0.4-bin.jar SQL 代码 CREATE TABL ...

  9. 干货 | Java8 新特性教程

    本教程翻译整理自 https://github.com/winterbe/java8-tutorial 本教程首发自个人网站: https://www.exception.site/java8/jav ...

  10. 前端(各种demo)二:左侧导航栏的折叠和打开(不使用js)基础版和升级版

    1.给div设置定位. 复习一下—— css中position有五种属性: static:默认值,没有定位 absolute:绝对定位,相对于父级元素进行定位 relative:相对定位 fixed: ...