对象遍历问题及解决方案
1. 检测某个成员(属性/键)是否属于这个对象?
in:检测成员是否属于这个对象「特点:不论是私有属性,还是公有的属性,只要有则检测结果就是 true」
function Fn() {
/*
* EC(FN)
* 初始创建Fn找个类的一个实例对象 0x000
* 初始THIS:this->0x000
*/
let total = 0; //上下文的私有变量 和实例对象没有必然的联系
this.x = 10; //this.xxx=xxx 都是给实例对象设置的私有属性和方法
this.y = 20;
this.say = function () {
//0x000.say=0x100 0x001.say=0x101
console.log("SAY");
};
/* 如果不设置返回值,或者返回值是一个基本类型值,默认都会把实例对象 0x000 返回;如果手动返回的是一个引用数据类型值,则以自己返回的为主; */
// return {
// name: 'zhufeng'
// };
}
let f1 = new Fn(); //->0x000
console.log("say" in f1); //->true
console.log('hasOwnProperty' in f1)//->true
hasOwnProperty 在 f1 的公有属性上
2. 检测是否属于这个对象的私有属性
hasOwnProperty:用来检测当前成员是否为对象的私有属性「特点:只有是私有属性,结果才是 ture,哪怕有这个属性,但是属于公有的属性,结果也是 false」
function Fn() {
/*
* EC(FN)
* 初始创建Fn找个类的一个实例对象 0x000
* 初始THIS:this->0x000
*/
let total = 0; //上下文的私有变量 和实例对象没有必然的联系
this.x = 10; //this.xxx=xxx 都是给实例对象设置的私有属性和方法
this.y = 20;
this.say = function () {
//0x000.say=0x100 0x001.say=0x101
console.log("SAY");
};
/* 如果不设置返回值,或者返回值是一个基本类型值,默认都会把实例对象 0x000 返回;如果手动返回的是一个引用数据类型值,则以自己返回的为主; */
// return {
// name: 'zhufeng'
// };
}
let f1 = new Fn(); //->0x000
console.log(f1.hasOwnProperty("say")); //->true
f1.hasOwnProperty('hasOwnProperty')` `//->false`
说明‘hasOwnProperty’不是它的私有属性,也就是它的公有属性「前提基于 in 检测出来的结果是 true」
3. 编写检测一个属性是对象的共有属性
function hasPubProperty(attr, obj) {
//方案一:
return attr in obj && !obj.hasOwnProperty(attr);
//方案二:共有属性实在obj所属类的原型上,我们去获得这个obj的原型即可。如果没有共有属性,则遍历到Object的原型是null
let proto = Object.getPrototypeOf(obj);
if (proto !== null) {
if (proto.hasOwnProperty(attr)) {
return true;
}
proto = Object.getPrototypeOf(proto);
}
return false;
}
let obj = {
name: "hahha",
age: "hahaha",
};
console.log(hasPubProperty("name", obj));
console.log(hasPubProperty("age", obj));
4. 如何遍历对象
for in
let sy = Symbol();
let obj = {
name: "zhufeng",
age: 12,
3: "哈哈哈",
0: "zhouxiaotian",
[sy]: 100,
};
Object.prototype.AAA = 100;
for (let key in obj) {
console.log(key);
}
for in 遍历的特点:
- 不能遍历 symbol 的私有属性
- 可以遍历原型上扩展的共有属性「内置的公共属性是不可枚举的(就是无法遍历到的)」
- 数字属性优先遍历,并且从小到大遍历(不会严格按照属性书写的顺序)
需求1:避免遍历公共的
for (let key in obj) {
if (!obj.hasOwnProperty(key)) break; //已经遍历到公共的,则私有已经遍历完,结束循环
console.log(key); //->'name'
}
需求2:只想遍历私有的,包含 Symbol 的
let keys = [
...Object.getOwnPropertyNames(obj),
...Object.getOwnPropertySymbols(obj),
];
keys.forEach((key) => {
console.log(key, obj[key]);
});