【每日笔记·6】对象

202 阅读2分钟

1.属性描述符

var myObject = {
    a: 2,
};

Object.getOwnPropertyDesciptor(myObject,"a",{
    value: 2, // 值
    writable: true, // 是否可以修改属性的值
    configurable: true, // 是否可以配置
    enumerable: true // 可枚举
});

  • configurable
confifurable: true  可以使用defineProperty()方法来修改属性描述符。

configurable: false  不可配置,是单向操作,无法撤销,同时会禁止删除这个属性。

但有一个小例外:属性设置为configurable: false,我们可以把writable的状态由true改为false,但无法由false改为true

var myObject = {
    a: 2
};
myObject.a // 2
delete myObject.a;
myObject.a // undefined

Object.defineProperty(myObject, "a", {
    value: 2,
    writable: true,
    configurable: false,
    enumberable: true
});
myObject.a // 2
delete myObject.a;
myObject.a // 2  删除失败
  • enumerable
是否可枚举。是否可以出现在对象属性的遍历中。

var myObject = {};
Object.defineProperty(myObject,"a",{
    value: 2,
    enumerable: true, // 让a像普通属性一样可以枚举
});
Object.defineProperty(myObject,"b",{
    value: 3,
    enumerable: false, // 让b不可枚举
});
("b" in myObject); // true
myObject.hasOwnProperty("b"); // true

for(var k in myObject) {
    console.log(k,myObject[k]);
}
// a 2

inhasOwnProperty()区别在于是否查找[[prototype]]链。

还有别的方式区分是否可枚举:

var myObject = {};
Object.defineProperty(myObject,"a",{
    value: 2,
    enumerable: true,
});
Object.defineProperty(myObject, "b",{
    value: 3,
    enumerable: false,
});

myObject.propertyIsEnumerable("a"); // true
myObject.propertyIsEnumerable("b"); // false

Object.keys(myObject); // ["a"]
Object.getOwnPropertyNames(myObject); // ["a","b"]

propertyIsEnumerable  检查给定的属性名是否直接存在于对象中(而不是原型链上)并且满足enumerable: true

Object.keys()  返回一个数组,包含所有可枚举属性。Object.getOwnPropertyNames()  返回一个数组,包含所有属性,无论是否可枚举。

2.不变性

  • 对象常量
真正的常量属性(不可修改、重定义或者删除):

var myObject = {};
Object.defineProperty(myObject, "FAVORITE_NUMBER",{
    value: 4,
    writeable: false,
    configurable: false,
});

  • 禁止扩展(Object.preventExtensions())
禁止对象添加新属性并且保留已有属性。

var myObject = {
    a: 2
};
Object.preventExtensions(myObject);
myObject.b = 3;
myObject.b; // undefined
  • 密封(Object.seal())
不能添加新属性也不能重新配置或者删除任何现有属性(可以修改属性的值)。

这个方法实际上会在一个现有对象上调用Object.preventExtensions()并把所有现有属性标记为configurable: false

  • 冻结
禁止对于对象本身及其任意直接属性的修改。

这个方法实际上会在一个现有对象上调用Object.freeze()并把所有数据访问属性标记为writable: false

3.Getter和Setter 访问描述符

var myObject = {
    // 给a定义一个getter
    get a() {
        return this._a_;
    },
    // 给a定义一个setter
    set a(val) {
        this._a_ = val * 2,
    },
};

myObject.a = 2; // 设置属性值时调用setter
myObject.a; // 4 获取属性值时调用getter

4.存在性

var myObject = {
    a: 2
};
("a" in myObject); // true
("b" in myObject); // false

myObject.hasOwnProperty("a"); // true
myObject.hasOwnProperty("b"); // false

in操作符会检查属性是否在对象及其[[Prototype]]原型链中。

hasOwnProperty()会检查属性是否在myObject对象中,不会检查[[Prototype]]链。

所有的普通对象都可以通过对于Object.prototype的委托来访问hasOwnProperty()。但是Object.create(null)不会连接Object.prototype(),所以在这种情况下就会失败。