论Object.keys(), Object.getOwnPropertyNames(), for in, Object.getOwnPropertySymbol()区别
前不久,一朋友求助,让我给解释一波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,简单总结一下:
- keys() => 输出为一个数组,取到的是 obj 的所有的自身可枚举属性。其功能和for in + hasOwnProperty()功能是一致的
- getOwnPropertyNames() => 输出为一个数组,取到的是 obj 的所有自身属性。(可枚举、不可枚举,但不包括symbol类型的属性)
- getOwnPropertySymbol() => 输出为一个数组,取到的是 obj 的所有自身的Symbol属性
- for in => 遍历 obj 的所有属性,包括自身属性和原型上的所有可枚举的属性
- 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"}
对比上面输出日志,我不难发现:
- defineProperty() 和 prototype 添加的属性默认是不可枚举的。
- defineProperty() 添加的属性时属于自身属性。
哈哈哈,能读到这儿,我想未来的我,可能没有晕吧。
管他呢,简单提个醒吧,方便以后自己更快速地懂这些东西;
- for in 没有 func1, 是因为defineProperty()定义的是自身属性,且默认不可枚举。protoName 是在原型 prototype 上,所以会有。
- hasOwnProperty() 是只取自身属性,所以 原型上的 protoName, func3 都没有。
- keys() 所有的自身可枚举属性, 所以 protoName 和 func3 首先排除了。c 和 func2 是不可枚举。
- getOwnPropertyNames() 所有自身属性。所以原型上的protoName 和 func3 都被排除了。
- JSON.stringify() 只要自身的,且可枚举的属性。认真看看,转字符串和直接输出的 obj 有多大区别。
所以,网上关于深度克隆一个对象的方式 ---- JSON.parse(JSON.stringify(obj)),严格来说,是不正确的。
然而此时,我就有问题要讲啦。
实际项目中我们应该怎么选,如何规避上述的问题呢?
还待高人指点迷津,
抑或,以后自己去发现。
今天被同事骗了,说 撒拉黑 是 你好 的意思。来了一个男同事,我就对他说了:
-- 撒拉黑
-- 滚犊子
啊,留我一人在风中凌乱...
.>|=|<.
论Object.keys(), Object.getOwnPropertyNames(), for in, Object.getOwnPropertySymbol()区别的更多相关文章
- for in,Object.keys()与for of的用法与区别
Array.prototype.sayLength=function(){ console.log(this.length); } let arr = ['a','b','c','d']; arr.n ...
- for in,Object.keys和Object.getOwnPropertyNames的区别
var parent = Object.create(Object.prototype, { a: { value: 1, writable: true, enumerable: true, conf ...
- Object.keys() https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用for...in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in ...
- Object.keys的‘诡异’特性,你值得收藏!
先从'诡异'的问题入手 例1: 纯Number类型的属性 const obj = { 1: 1, 6: 6, 3: 3, 2: 2 } console.log('keys', Object.keys( ...
- Object.keys(),Object.values(),Object.entries()
(1)Object.keys() // 返回数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名. eg:var obj = {a:1,b:'gy'} Ob ...
- 关于Object.keys()和Object.values()的使用
关于Object.keys()和Object.values()的使用 1. 关于Object.keys() 1) 处理对象,返回可枚举的所有可枚举属性的字符串数组 let person ={ name ...
- JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别
ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...
- Object.keys、Object.getOwnPropertyNames区别
用途 Object.keys 定义:返回一个对象可枚举属性的字符串数组: Object.getOwnPropertyNames 定义:返回一个对象可枚举.不可枚举属性的名称: 属性的可枚举性.不可枚举 ...
- [转] JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的区别
ECMAScript将对象的属性分为两种:数据属性和访问器属性.每一种属性内部都有一些特性,这里我们只关注对象属性的[[Enumerable]]特征,它表示是否通过 for-in 循环返回属性,也可以 ...
- 小tips:JS之for in、Object.keys()和Object.getOwnPropertyNames()的区别
for..in循环 使用for..in循环时,返回的是所有能够通过对象访问的.可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例.这里需要注意的是使用for-in返回的属性因各个浏览器厂 ...
随机推荐
- SQLSERVER CTE表 row_number()字段 BUG
当CTE中 引用的子视图的字段用了 row_number() over等那么有可能造成row_number() 的对应关系出错的问题 所以CTE row_number() over 排序字段 必须 ...
- JavaScript 世界万物诞生记
一. 无中生有 起初,什么都没有.造物主说:没有东西本身也是一种东西啊,于是就有了null: 现在我们要造点儿东西出来.但是没有原料怎么办?有一个声音说:不是有null嘛?另一个声音说:可是null代 ...
- Docker命令详解(run篇)
命令格式:docker run [OPTIONS] IMAGE [COMMAND] [ARG...] Usage: Run a command in a new container 中文意思为:通过r ...
- 图像分类(一)GoogLenet Inception_V1:Going deeper with convolutions
论文地址 在该论文中作者提出了一种被称为Inception Network的深度卷积神经网络,它由若干个Inception modules堆叠而成.Inception的主要特点是它能提高网络中计算资源 ...
- javaweb(3)之JSP&EL&JSTL
JSP(Java Server Page) 介绍 什么是 JSP ? 从用户角度看,JSP 就是一个网页. 从开发者角度看,它其实就是一个继承了 Servlet 的 java 类,所以可以直接说 JS ...
- Linux操作系统加固
1. 账号和口令 1.1 禁用或删除无用账号 减少系统无用账号,降低安全风险. 操作步骤 使用命令 userdel <用户名> 删除不必要的账号. 使用命令 passwd -l <用 ...
- ARIMA模型总结
时间序列建模基本步骤 获取被观测系统时间序列数据: 对数据绘图,观测是否为平稳时间序列:对于非平稳时间序列要先进行d阶差分运算,化为平稳时间序列: 经过第二步处理,已经得到平稳时间序列.要对平稳时间序 ...
- 大数据小视角3:CarbonData,来自华为的中国力量
连续两篇文章都聊了不同的存储格式,这篇我们继续深入来看看在存储格式的演变之上有什么新的"黑科技".华为公司在2016年开源了类parquet的列存格式:CarbonData,并且贡 ...
- ASP.NET MVC案例教程(二)
ASP.NET MVC案例教程(二) 让第一个页面跑起来 现在,我们来实现公告系统中的第一个页面——首页.它非常简单,只包括所有公告分类的列表,并且每个列表项是一个超链接.其中分类数据是用我们的Moc ...
- acm 2015北京网络赛 F Couple Trees 主席树+树链剖分
提交 题意:给了两棵树,他们的跟都是1,然后询问,u,v 表 示在第一棵树上在u点往根节点走 , 第二棵树在v点往根节点走,然后求他们能到达的最早的那个共同的点 解: 我们将第一棵树进行书链剖,然后第 ...