检测某属性是否属于某实例(不论私有还是公有),[属性] in [对象]
检测某属性是否属于某实例的私有属性[对象].hasOwnProperty([属性])
[属性] in [对象]:基于原型链机制查找,在当前对象中查找到的为私有属性,基于__proto__查找的属于公有属性(公有、私有针对[对象]而言)- 先查找当前对象是否存在此属性,若存在,返回true;
- 若不存在会基于[对象]的原型链__proto__查找到其所属类的原型prototype上的属性(对[对象]来说为公共属性),存在返回true;
- 若还不存在,还会基于此原型prototype的__proto__查找(不是被new出来的prototype属于对象类),直至找到Object.prototype位置,存在则返回true,不存在返回false;
[对象].hasOwnProperty([属性]):在[对象]地址空间中查找[属性],若存在返回true;不存在返回false;(查找到的是[对象]的私有属性)
问题:检测某个[属性]是否为这个[对象]的公有属性
//此方法思想:属性attr是对象obj的一个属性,并且属性attr不是对象obj的私有属性,那么属性attr就是公有属性
const hasPubProperty = function hasPubProperty(obj, attr) {
return (attr in obj) && !obj.hasOwnProperty(attr);
};
//此方法有瑕疵:如果attr既是对象obj的私有属性也是对象obj的公有属性呢,这个方法就会返回false,但是属性attr是对象obj的公有方法啊
上述方法的缺陷,详看下图:
- 对于对象a1,方法m1属于其私有方法,方法M1既是a1的私有方法也是a1的公有方法;方法M2是a1的公有方法;
- 对于对象a2,方法m2是a2的私有方法,方法M1和M2的a2的公有方法;
classDiagram
类A的prototype属性 <|-- 实例a1
类A的prototype属性 <|-- 实例a2
类A的prototype属性 : +...
类A的prototype属性 : +...
类A的prototype属性: +供所属实例调用的公共属性和方法M1()
类A的prototype属性: +供所属实例调用的公共属性和方法M2()
class 实例a1{
+...
+私有方法m1()
+私有方法M1()
}
class 实例a2{
-...
-私有方法m2()
}
解决方法:
- 不论私有中是否存在此属性,只要在其原型链中存在的属性就为公有属性
- 首先获取当前实例this(obj)的原型对象A,看A中是否存在attr这个属性,
- 存在则直接返回true,说明attr是它的一个公有属性;
- 如果不存在,则找A的原型对象...直到找到Object.prototype;
- 如果整个过程中都没有找到对应的属性,则说明attr不是他的公有属性,返回false即可;
- Object.getPrototypeOf(实例):获取某个实例的原型对象;
- 把检测其公有属性的方法拓展到对象类的原型上【基类的原型上Object.prototype】
Object.prototype.hasPubProperty = function hasPubProperty(attr){
//获取当前对象的原型
let proto = Object.getPrototypeOf(this);
//截止到基类原型上的原型链,就停止循环,Object.prototype.__proto__=null;null转换为布尔类型为false
while (proto) {
//找到属性就返回true
if (proto.hasOwnProperty(attr)) return true;
//没有找到属性,就继续往上级原型找
proto = Object.getPrototypeOf(proto);
}
//一直找不到就返回false
return false;
};