从零开始学_JavaScript_系列(35)——继承与遍历的对照表

来源:互联网 发布:final cut for mac 编辑:程序博客网 时间:2024/05/29 04:49

继承

属性的继承有多种方式,但简单来说,分为继承后在本身属性上,以及在继承的属性在原型链上。

前者的典型情况是通过call、apply或者Object.assign()等,他们之间还略有区别(但不影响遍历)。

后者的典型情况是通过prototype来继承,属性不在对象本身上,而是在例如 obj.__proto__ 上,或者更深一层等。

遍历

遍历的方法也有很多种,兼容旧版本的常见方法是for…in,之后还有Object.keys()等。

当我们需要遍历对象时,属性位于哪里,以及是否可枚举,将影响遍历的结果。故这里列出一个表格作为对照参考。

方法 原型链继承(原型链上的属性) call继承(在实例上的属性) 普通属性,但enumerable为false for…in 显示 显示 不显示 Object.keys() 不显示 显示 不显示 JSON.stringify() 不显示 显示 不显示 Object.getOwnPropertyNames() 不显示 显示 显示 Reflect.ownKeys() 不显示 显示 显示 Object.getOwnPropertySymbols() 不显示 不显示 不显示

总结一下:

遍历要求 方法 普通的情况 Object.keys() 本身 + 原型链 for…in 本身,且包括枚举属性被设置为false的key Object.getOwnPropertyNames()
Reflect.ownKeys() 兼容低版本IE for…in(但注意原型链上的是否需要) 只获取不能枚举的属性 Object.getOwnPropertyNames()获取全部
再排除Object.keys() 只获取原型链上(不包括自己的) for..in先获取
再排除掉普通的 原型链上包括不可枚举的 手动递归__proto__属性
然后每一层Object.getOwnPropertyNames()获取 原型链上,只要不可枚举的 手动递归__proto__属性
然后每一层先获取全部再排除普通

验证代码如下:

```//继承方式//原型链继承function Child() {    this.a = "a";}function Father() {    this.b = "b";}Child.prototype = new Father();let foo = new Child();//call继承function AnotherFather() {    this.b = "b";}function AnotherChild() {    this.a = "A";    AnotherFather.call(this);}let bar = new AnotherChild();//其他,普通继承但enumberable值为falselet obj = Object.defineProperty({}, "a", {    value: "a",    enumerable: false})//遍历方式//for...inconsole.log("for...in");let arrFoo = [];for (let i in foo) {    arrFoo.push(i);}let arrBar = [];for (let i in bar) {    arrBar.push(i);}let objArr = [];for (let i in obj) {    objArr.push(i);}console.log(arrFoo);    //["a", "b"]console.log(arrBar);    //["a", "b"]console.log(objArr);    //[]console.log("-----");//Object.keys();console.log("Object.keys()");console.log(Object.keys(foo));  //["a"]console.log(Object.keys(bar));  //["a", "b"]console.log(Object.keys(obj));  //[]console.log("-----");//JSON.stringify()console.log("JSON.stringify()");console.log(JSON.stringify(foo));   //{"a":"a"}console.log(JSON.stringify(bar));   //{"a":"A","b":"b"}console.log(JSON.stringify(obj));   //{}console.log("-----")//Object.getOwnPropertyNames()返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。console.log("Object.getOwnPropertyNames()");console.log(Object.getOwnPropertyNames(foo));   //["a"]console.log(Object.getOwnPropertyNames(bar));   //["a", "b"]console.log(Object.getOwnPropertyNames(obj));   //["a"]console.log("-----");//Reflect.ownKeys()返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举。console.log("Reflect.ownKeys()");console.log(Reflect.ownKeys(foo));   //["a"]console.log(Reflect.ownKeys(bar));   //["a", "b"]console.log(Reflect.ownKeys(obj));   //["a"]console.log("-----");//Object.getOwnPropertySymbols()返回一个数组,包含对象自身的所有Symbol属性console.log("Object.getOwnPropertySymbols()");console.log(Object.getOwnPropertySymbols(foo));   //[]console.log(Object.getOwnPropertySymbols(bar));   //[]console.log(Object.getOwnPropertySymbols(obj));   //[]//for...of只能用于迭代有迭代器接口的对象,普通对象是没有这个接口的,所以不行

“`

阅读全文
0 0