您的位置:首页 > Web前端 > JavaScript

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

2017-05-31 11:36 381 查看

继承

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

前者的典型情况是通过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的keyObject.getOwnPropertyNames()
Reflect.ownKeys()
兼容低版本IEfor…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值为false
let obj = Object.defineProperty({}, "a", {
value: "a",
enumerable: false
})

//遍历方式

//for...in
console.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只能用于迭代有迭代器接口的对象,普通对象是没有这个接口的,所以不行


“`
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐