检测属性方法
in
-
检测当前对象是否存在某个属性,不论是公有还是私有,只要有,返回 true
[attr] in [object]
function Fn() {
this.age = 14;
this.name = "lion";
}
Fn.prototype.category = "animal";
let f = new Fn();
console.log("name" in f); // true
console.log("category" in f); // true
hasOwnProperty
-
检测一个属性是不是这个对象的私有属性,如果是,返回true
[object].hasOwnProperty([attr])
function Fn() {
this.age = 14;
this.name = "lion";
}
Fn.prototype.category = "animal";
let f = new Fn();
console.log(f.hasOwnProperty("name")); // true
console.log(f.hasOwnProperty("category")); // false
尝试封装检测公有属性
- 了解了
in
和hasOwnProperty
之后我们可以尝试封装检测公有属性的方法
写出来大概是如下这样:
Object.prototype.hasPubProperty = function (attr) {
return attr in obj && !obj.hasOwnProperty(attr);
}
- 但是这个是有弊端的,比如:某个属性既是私有的,也是公有的,就检测不出来了
Object.prototype.hasPubProperty = function (attr) {
return attr in this && !this.hasOwnProperty(attr);
}
function Fn() {
this.age = 14;
this.name = "lion";
}
Fn.prototype.category = "animal";
Fn.prototype.name = "bird";
let f = new Fn();
// name既是公有的也是私有的
console.log(f.hasPubProperty("name")); // false
console.log(f.hasPubProperty("category")); // true
这样肯定不行,有没有什么方法可以避免这个问题,接下来需要看一下 Object 的其它几个方法
检测公有属性
- 期望结果如下:
function Fn() {
this.age = 14;
this[A] = 100;
this.name = "lion";
}
let A = Symbol("a");
Fn.prototype.name = "bird";
Fn.prototype[A] = 200;
let f = new Fn();
// age是私有方法
console.log(f.hasPubProperty("age")); // false
// name既是公有的也是私有的
console.log(f.hasPubProperty("name")); // true
// A(Symbol)既是公有的也是私有的
console.log(f.hasPubProperty(A)); // true
Object.getPrototypeOf
如果了解前置知识,可直接跳到封装方法处
前置知识
ES5新增方法
Object.getPrototypeOf([object])
方法返回指定对象自身的原型
Fn.prototype === Object.getPrototypeOf(f); // true
封装方法
- 借用原型链查找公有属性
Object.prototype.hasPubProperty = function (attr) {
let self = this,
prototype = Object.getPrototypeOf(self);
while (prototype) {
// 检测是否存在attr这个属性
if (prototype.hasOwnProperty(attr)) return true;
// 一直按照原型链查找
prototype = Object.getPrototypeOf(prototype);
}
return false
}
- 因为用到了
hasOwnProperty
,它不仅能检测可枚举属性还可以检测内置属性
console.log(f.hasPubProperty("toString")); // true
console.log(f.hasPubProperty("valueOf")); // true
Object.keys
如果了解前置知识,可直接跳到封装方法处
前置知识
ES5新增方法
Object.keys([object])
方法会返回一个数组,数组里面存放指定对象自身的可枚举属性Object.keys([object])
方法返回非 Symbol 私有属性的数组
Object.prototype.xx = "xx";
let obj = {
name: "lion",
age: 12,
3: 200,
0: 100,
[Symbol("a")]: function () {}
}
console.log(Object.keys(obj)); // [ '0', '3', 'name', 'age' ]
- 如果想获取 Symbol 私有属性,可以使用
Object.getOwnPropertySymbols(obj)
console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(a) ]
- 如果想获取所有私有属性(包括Symbol)到一个数组中,可以这么写
[...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
// ['0', '3', 'name', 'age', Symbol(a)]
封装方法
Object.prototype.hasPubProperty = function (attr) {
var self = this,
prototype = Object.getPrototypeOf(self);
while (prototype) {
// 检测是否存在attr这个属性
var keys = Object.keys(prototype);
// 检测浏览器是否支持Symbol
if (typeof Symbol !== "undefined") {
// 如果支持,把Symbol属性合并到数组中
keys = keys.concat(Object.getOwnPropertySymbols(prototype));
}
// 一直按照原型链查找
prototype = Object.getPrototypeOf(prototype);
}
return false
}
- 注意:内置属性不可以枚举,
Object.keys([object])
方法检测不到内置属性
console.log(f.hasPubProperty("toString")); // false
console.log(f.hasPubProperty("valueOf")); // false