前不久,一朋友求助,让我给解释一波Object.keys(), Object.getOwnPropertyNames(), for in的区别,面试中好几次呗问了。所以,抽了点时间看了看,大概把我看的过程中做的demo记录一下。

看了网上一些关于介绍Object.keys(), Object.getOwnPropertyNames(), for in, Object.getOwnPropertySymbol()的区别,都介绍得不是很详细,不容易理解,今天抽空来说说这三者的区别。

废话不多说,直接上代码。

defineProperty() => 给对象添加单个属性及属性值的,并规定该属性是否可枚举,默认是不可枚举的;所以正常情况下,我们给对象添加单个属性时,只需要用.操作即可。亦,obj.e = 2。这种方式添加的属性默认是可枚举的。

我们通过设置 enumerable 的值来设置属性是否可枚举。

来,下面demo运行起来。

var obj = { a: "1", b: "2"};
Object.prototype.protoName = "proto foobar";
var foo = Symbol("foo");
// 给obj 添加了一个键名为 c, foo 变量值
Object.defineProperty(obj, "c", {
value: "3",
enumerable: false // 定义是否可枚举,默认 false
})
Object.defineProperty(obj, "d", {
value: "4",
enumerable: true // 定义是否可枚举
})
Object.defineProperty(obj, foo, {
value: "foobar",
enumerable:false
});

打印的结果为:

{a: "1", b: "2", d: "4", c: "3", Symbol(foo): "foobar"}

OK,接下来我们,我们输出日志看看...

for (var i in obj) {
console.log(" for in : ", i); // 输出 a b d protoName
if (obj.hasOwnProperty(i)) {
console.log("obj.hasOwnProperty(i): ", i); // a b d
}
}
console.log("Object.keys(obj): ", Object.keys(obj)); // ["a", "b", "d"]
console.log("Object.getOwnPropertyNames(obj): ", Object.getOwnPropertyNames(obj)); // ["a", "b", "c", "d"]
console.log("Object.getOwnPropertySymbols(obj): ", Object.getOwnPropertySymbols(obj)); // [Symbol(foo)]
// JSON.stringify(obj) 只能将自身的属性转化成字符串
console.log("JSON.stringify(obj): ", JSON.stringify(obj)); // {"a": "1", "b": "2", "d": "4"}

就上面demo,简单总结一下:

  1. keys() => 输出为一个数组,取到的是 obj 的所有的自身可枚举属性。其功能和for in + hasOwnProperty()功能是一致的
  2. getOwnPropertyNames() => 输出为一个数组,取到的是 obj 的所有自身属性。(可枚举、不可枚举,但不包括symbol类型的属性)
  3. getOwnPropertySymbol() => 输出为一个数组,取到的是 obj 的所有自身的Symbol属性
  4. for in => 遍历 obj 的所有属性,包括自身属性和原型上的所有可枚举的属性
  5. JSON.stringify() => 只能将自身的可枚举的属性转化成字符串

OK, 运行完上面demo后发现,问题是不是轻轻松松地解决了喂,然而,并没有。仔细对比一下上面的日志,然后,来,接着往下走。

for in obj => 能遍历obj的所有属性,包括原型上的属性。(包括原型上的可枚举的属性和方法),有点蒙比了?

如果确实蒙比了,我们接着往下敲代码

Object.defineProperty(obj, "func1", {
value: function() {console.log("func1")}
})
Object.defineProperty(obj, "func2", {
value: function() {
console.log("func2")
},
enumerable: true
}) // 来,我们在在原型上添加一个方法
Object.prototype.func3 = function() {
console.log("func3")
} for (var i in obj) {
console.log(" for in : ", i); // 输出 a b d protoName func2 func3
if (obj.hasOwnProperty(i)) {
console.log("obj.hasOwnProperty(i): ", i); // a b d func2
}
}
console.log("Object.keys(obj): ", Object.keys(obj)); // ["a", "b", "d", "func2"]
console.log("Object.getOwnPropertyNames(obj): ", Object.getOwnPropertyNames(obj)); // ["a", "b", "c", "d", "func1", "func2"]
console.log("Object.getOwnPropertySymbols(obj): ", Object.getOwnPropertySymbols(obj)); // [Symbol(foo)]
console.log("JSON.stringify(obj): ", JSON.stringify(obj)); // {"a":"1","b":"2","d":"4"}
console.log("obj: ", obj); // {a: "1", b : "2", d : "4", func2 : ƒ (), c : "3", func1 : ƒ (), Symbol(foo) : "foobar"}

对比上面输出日志,我不难发现:

  1. defineProperty() 和 prototype 添加的属性默认是不可枚举的。
  2. defineProperty() 添加的属性时属于自身属性。

哈哈哈,能读到这儿,我想未来的我,可能没有晕吧。

管他呢,简单提个醒吧,方便以后自己更快速地懂这些东西;

  1. for in 没有 func1, 是因为defineProperty()定义的是自身属性,且默认不可枚举。protoName 是在原型 prototype 上,所以会有。
  2. hasOwnProperty() 是只取自身属性,所以 原型上的 protoName, func3 都没有。
  3. keys() 所有的自身可枚举属性, 所以 protoName 和 func3 首先排除了。c 和 func2 是不可枚举。
  4. getOwnPropertyNames() 所有自身属性。所以原型上的protoName 和 func3 都被排除了。
  5. JSON.stringify() 只要自身的,且可枚举的属性。认真看看,转字符串和直接输出的 obj 有多大区别。

所以,网上关于深度克隆一个对象的方式 ---- JSON.parse(JSON.stringify(obj)),严格来说,是不正确的。

然而此时,我就有问题要讲啦。

实际项目中我们应该怎么选,如何规避上述的问题呢?

还待高人指点迷津,

抑或,以后自己去发现。


今天被同事骗了,说 撒拉黑你好 的意思。来了一个男同事,我就对他说了:

-- 撒拉黑

-- 滚犊子

啊,留我一人在风中凌乱...

   .>|=|<.

论Object.keys(), Object.getOwnPropertyNames(), for in, Object.getOwnPropertySymbol()区别的更多相关文章

  1. for in,Object.keys()与for of的用法与区别

    Array.prototype.sayLength=function(){ console.log(this.length); } let arr = ['a','b','c','d']; arr.n ...

  2. for in,Object.keys和Object.getOwnPropertyNames的区别

    var parent = Object.create(Object.prototype, { a: { value: 1, writable: true, enumerable: true, conf ...

  3. Object.keys() https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys

    Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用for...in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in ...

  4. Object.keys的‘诡异’特性,你值得收藏!

    先从'诡异'的问题入手 例1: 纯Number类型的属性 const obj = { 1: 1, 6: 6, 3: 3, 2: 2 } console.log('keys', Object.keys( ...

  5. Object.keys(),Object.values(),Object.entries()

    (1)Object.keys() //       返回数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名. eg:var obj = {a:1,b:'gy'} Ob ...

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

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

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

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

  8. Object.keys、Object.getOwnPropertyNames区别

    用途 Object.keys 定义:返回一个对象可枚举属性的字符串数组: Object.getOwnPropertyNames 定义:返回一个对象可枚举.不可枚举属性的名称: 属性的可枚举性.不可枚举 ...

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

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

  10. 小tips:JS之for in、Object.keys()和Object.getOwnPropertyNames()的区别

    for..in循环 使用for..in循环时,返回的是所有能够通过对象访问的.可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例.这里需要注意的是使用for-in返回的属性因各个浏览器厂 ...

随机推荐

  1. 网站ASHX不执行故障

    今天修改之前做的一个网站,添加了ashx文件,但调试时发现里面的代码不执行. 检查webconfig文件发现其中有一项配置了ashx的处理方式: <system.web> <http ...

  2. python语法_if判断

    age_of_princal = 56 guess_age = int(input("e guess a age:")) if guess_age == age_of_princa ...

  3. [No000018D]Vim快速注释/取消注释多行的几种方法-Vim使用技巧(2)

    在使用Vim进行编程时,经常遇到需要快速注释或取消注释多行代码的场景,Vim教程网根据已有的教程介绍,总结了三种快速注释/取消注释多行代码的方法. 一.使用Vim可视化模式快速注释/取消注释多行 在V ...

  4. .net 平台 统计图表展示控件fusioncharts

    https://www.fusioncharts.com/javascript-chart-fiddles/

  5. TCP/IP的分层管理

    网络基础TCP/IP 我们通常所使用的网络(包括互联网)均是在TCP/IP协议族的基础上运作的.HTTP属于它内部的一个子集 TCP/IP协议族按层次分为:应用层,传输层,网络层和数据链路层(更好的划 ...

  6. Delphi 中的 XMLDocument 类详解(9) - 关于 HasChildNodes 与 IsTextElement

    unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...

  7. tarjan代码

    还有五天就是NOIP2018了……本蒟蒻还要复习期中考试,因此实在没有时间写博客了(各种找借口).这里就放一下代码 //Tarjan缩点 //题目描述:给一个有向图.每个点有一个权值,求权值和最大的路 ...

  8. windows 2008R2部署网站后出现 ‘PageHandlerFactory-Integrated’ 的解决办法

    原因:运行4.0的网站,需要用aspnet_regiis注册4.0框架,然后用4.0的Class池,就可以运行4.0的web项目了. 解决方法:1.在cmd中切换到4.0所在的目录,命令如下:cd C ...

  9. 关于systemctl

    systemctl是CentOS7的服务管理工具中主要的工具,它融合之前service和chkconfig的功能于一体. 启动一个服务:systemctl start firewalld.servic ...

  10. 20175211 2018-2019-2 《Java程序设计》第二周学习总结

    目录 教材学习内容总结 第二章 第三章 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 其他(感悟.思考等,可选) 学习进度条 参考资料 教材学习内容总结 第二章 ...