js 对象中默认的数据属性和访问器属性理解

新建对象最原始的方法:

var obj = new Object();// == var obj = {}
obj.name = "red";
obj.job = "Software Engineer";
obj.sayHey = function(){
    alert("大家好,我的名字是:" + this.name + "!");
}
console.log(obj);
obj.sayHey();

后来演变为对象字面量形式:

var obj = {
    name : "blue",
    job  : "Software Engineer",
    sayHey : function(){
        alert("大家好,我的名字是:" + this.name + "!");
    }
}
obj.sayHey();
console.log(obj);

js规定一些特性是为了实现JavaScript引擎用的。
上面的[[Configurable]] [[Enumerable]] [[Writable]] [[value]]四个数据属性(前三),都将被默认设置为了true,
而[[value]]特性被设置为指定的值。
修改默认数据属性特性的值,必须使用 Object.defineProperty()。
语法:Object.defineProperty(要修改哪个obj,要修改哪个属性,描述符对象[1-3个描述符+value])。

var person = {};
Object.defineProperty(person, "job", {
    writable : false,//Writable:是否可写。false:只读
    // configurable : true,//configurable:是否可删。false:不可删除。
    enumerable : true, //是否可枚举 for-in
    value : "Soft Engineer"
})
//是否可写
alert(person.job)
person.job = "aaaa"
alert(person.job)//also hahahah
//是否可删
delete person.job;
alert(person.job)
//for in 循环 是否可以返回属性
for(var i in person){
    console.log(person[i])
}

访问器属性:访问某个对象中,某个数据属性。

var book = {
    _year : 2004,
    edition: 1
}
Object.defineProperty(book,"year",{//year属性并未使用在对象方法内部
    get : function(){
        return this._year;//在对象方法内部-数据属性,常用标记前缀_
    },
    set : function(newValue){
        if(newValue > 2014){
            this._year = newValue;
            this.edition = newValue - 2004
        }
    }
});
book.year = 2015;//在外部调用year属性,都不变
console.log(book.edition)

一次定义多个属性:

var book = new Object();
Object.defineProperties(book,{
    _year : {//一个数据属性
        writable : true,
        value : 2004
    },
    edition : {//一个数据属性
        writable : true,
        value : 2
    },
    year : {//一个访问器属性,访问数据属性 _year
        get : function(){
            return this._year;
        },
        set : function(newValue){
            if(newValue > 2004){
                this._year = newValue;
                this.edition += newValue - 2004;
            }
        }
    }
});
book.year = 2008;

读取属性的特性:getOwnPropertyDescriptor(obj,"属性")

/*返回一个对象:*/
var descriptor1 = Object.getOwnPropertyDescriptor(book,"year");
console.log(descriptor1);//year是一个访问器属性
console.log(descriptor1.configurable);//false
var descriptor2 = Object.getOwnPropertyDescriptor(book,"_year");
console.log(descriptor2);//_year是一个数据属性
console.log(descriptor2.value);//2008
var descriptor3 = Object.getOwnPropertyDescriptor(book,"edition");
console.log(descriptor3.value);//6