1-1 定义属性

1-1-1 字面量形式创建

  1. var person1 = {
  2.   name: "Nicholas"
  3. };

1-1-2 使用Object构造函数创建

  1. var person2 = new Object();
  2. person2.name = "Nicholas";

1-2 属性探测

1-2-1 in

  1. 判断对象是否包含这个属性,包括(私有和公有)
var person1 = {
  name: "Nicholas",
  sayName: function() {
    console.log(this.name);
  }
};

console.log("name" in person1);           // true
console.log(person1.hasOwnProperty("name"));    // true

console.log("toString" in person1);         // true
console.log(person1.hasOwnProperty("toString"));  // false

1-2-2 hasOwnProperty

可以判断属性是私有的还是公有的
function Person(name,age){
  this.name = name
  this.age = age
}
Person.prototype = {
  constructor:Person,  
  sayName:function(){
    console.log(this.name);
  },
  sayAge(){
    console.log(this.age);
  }
}
var p = new Person("cheng",20)
console.log(p.hasOwnProperty("name")); // true  私有的
console.log(p.hasOwnProperty("sayName")); // false  公有的

1-3 删除属性 delete

var person1 = {
   name: "Nicholas"
};

console.log("name" in person1);     // true

delete person1.name;
console.log("name" in person1);     // false
console.log(person1.name);        // undefined

1-4 属性枚举

1-4-1 for - in

var obj = {name:"hhhh",age:18,skill:"javascript"}
for(let i in obj){
  console.log(i,obj[i]);
}

1-4-2 Object.keys( ) 可以获取可枚举属性的名字的数组

var obj = {name:"hhhh",age:18,skill:"javascript"}
var properties = Object.keys(obj)
console.log(properties);      // ["name", "age", "skill"]
for(let i =0;i<properties.length;i++){
  console.log("Name:"+properties[i]);  
  console.log("Value:"+obj[properties[i]])
}

1-4-3 for-in 和 Object.keys()区别

for-in 循环同时也会遍历原型属性 
Object.keys()只返回自有(实例)属性。

1-4-4 propertylsEnumerable( )方法

检查一个属性是否为可枚举的
var person1 = {
   name: "Nicholas"
};

console.log("name" in person1);               // true
console.log(person1.propertyIsEnumerable("name"));    // true

var properties = Object.keys(person1);

console.log("length" in properties);            // true
console.log(properties.propertyIsEnumerable("length")); // false
// length 它是Array. prototype的内建属性。你会发现很多原生属性默认都是不可枚举的。

1-5 属性类型

1-5-1 数据属性

// 目前为止用到的所有例子使用的都是数据属性。
var person1 = {
   name: "Nicholas",
    sayName: function() {
    console.log(this.name);
  }
}

1-5-2 访问器属性

访问器属性不包含值,而是定义了一个当属性被读取时调用的函数(称为getter)和一个当属性被写入时调用的函数(称为setter)。访问器属性仅需要getter或setter两者中的任意一个,当然也可以两者都有。
var person1 = {
  _name: "Nicholas",

get name() {
  console.log("Reading name");
  return this._name;
},

set name(value) {
  console.log("Setting name to %s", value);
  this._name= value;
  }
};

console.log(person1.name);    // "Reading name" then "Nicholas"

person1.name = "Greg";
console.log(person1.name);    // "Setting name to Greg" then "Greg"

1-6 属性特征

1-6-1 通用特征

有两个属性特征是数据和访问器属性都具有的。
[[Enumerable]]:  决定了你是否可以遍历该属性。
[[Configurable]]:  决定了该属性是否可配置(delete删除一个可配置的属性,或随时改变它。)

Object.defineProperty() : 改变属性特征 
接受3个参数:拥有该属性的对象、属性名和包含需要设置的特征的属性描述对象
var person1 = {
  name: "Nicholas"
};

Object.defineProperty(person1, "name", {
  enumerable: false
});

console.log("name" in person1);              // true
console.log(person1.propertyIsEnumerable("name"));   // false

var properties = Object.keys(person1);
console.log(properties.length);              // 0

Object.defineProperty(person1, "name", {
  configurable: false
});

// try to delete the Property
delete person1.name;
console.log("name" in person1);             // true
console.log(person1.name);                // "Nicholas"

Object.defineProperty(person1, "name", {        // error!!!
  configurable: true
});

1-6-2 数据属性特征

数据属性额外拥有两个访问器属性不具备的特征
[[Value]] : 包含属性的值
[[Writable]] : 指示该属性是否可以写入(是个布尔值)

通过这两个额外特征,你可以使用Object.defineProperty()完整定义一个数据属性
var person1 = {};

Object.defineProperty(person1, "name", {
  value: "Nicholas",
  enumerable: true,
  configurable: true,
  writable: true
});
//用Object.defineProperty()定义新的属性时记得为所有的特征指定一个值,否则布尔型的特征会被默认设置为false

1-6-3 访问器属性特征

[[Get]]和[[Set]],内含getter和setter函数
var person1 = {
  _name: "Nicholas"
};

Object.defineProperty(person1, "name", {
  get: function() {
    console.log("Reading name");
    return this._name;
  },
  set: function(value) {
     console.log("Setting name to %s", value);
     this._name= value;
  },
  enumerable: true,
  configurable: true
});

1-6-4 定义多重属性

使用Object.defineProperties()而不是Object.defineProperty(),可以为一个对象同时定义多个属性。
两个参数:需要改变的对象 和 一个包含所有属性信息的对象。
var person1 = {};

Object.defineProperties(person1, {

  // data property to store data
  _name: {
    value: "Nicholas",
    enumerable: true,
    configurable: true,
    writable: true
  },

  // accessor property
  name: {
    get: function() {
      console.log("Reading name");
      return this._name;
    },
    set: function(value) {
      console.log("Setting name to %s", value);
      this._name= value;
    },
    enumerable: true,
    configurable: true
  }
});

1-6-5 获取属性特征

用Object.getOwnPropertyDescriptor(对象,属性名)   这个方法只可用于自有属性
var person1 = {
  name: "Nicholas"
};

var descriptor = Object.getOwnPropertyDescriptor(person1, "name"); // 返回一个属性描述的对象

console.log(descriptor.enumerable);       // true
console.log(descriptor.configurable);      // true
console.log(descriptor.writable);     // true
console.log(descriptor.value);       // "Nicholas"

1-7 禁止修改对象

1-7-1 禁止扩展

Object.preventExtensions()    创建一个不可扩展的对象
Object.isExtensible()     判断对象是否是可扩展的
var person1 = {
  name: "Nicholas"
};

console.log(Object.isExtensible(person1));     // true

Object.preventExtensions(person1);
console.log(Object.isExtensible(person1));     // false

person1.sayName = function() {
  console.log(this.name);
};

console.log("sayName" in person1);         // false

1-7-2 对象封印

Object.seal()   封印一个对象   (一个被封印的对象是不可扩展的且其所有属性都不可配置)
这意味着不仅不能给对象添加新属性,也不能删除属性或改变其类型   (如果一个对象被封印,只能读写它的属性)
Object.isSealed()   判断对象是否被封印
var person1 = {
  name: "Nicholas"
};

console.log(Object.isExtensible(person1));   // true  可扩展的
console.log(Object.isSealed(person1));     // false  没有被封印

Object.seal(person1);                         // 将person1封印
console.log(Object.isExtensible(person1));   // false  不可扩展
console.log(Object.isSealed(person1));     // true   被封印了

person1.sayName = function() {
  console.log(this.name);
};

console.log("sayName" in person1);     // false   不可以再添加属性 

person1.name = "Greg";
console.log(person1.name);         // "Greg"

delete person1.name;                               // 不可删除属性
console.log("name" in person1);      // true
console.log(person1.name);         // "Greg"

var descriptor = Object.getOwnPropertyDescriptor(person1, "name");   
console.log(descriptor.configurable);  // false    不可配置的

1-7-3 对象冻结

Object.freeze()  冻结一个对象
Object.isFrozen()  判断一个对象是否被冻结
如果一个对象被冻结,则不能在其上添加或删除属性,不能改变属性类型,也不能写入任何数据属性。
(被冻结对象是一个数据属性都为只读的被封印对象。被冻结对象无法解冻)
var person1 = {
  name: "Nicholas"
};

console.log(Object.isExtensible(person1));     // true
console.log(Object.isSealed(person1));       // false
console.log(Object.isFrozen(person1));       // false

Object.freeze(person1);
console.log(Object.isExtensible(person1));     // false
console.log(Object.isSealed(person1));       // true
console.log(Object.isFrozen(person1));       // true

person1.sayName = function() {
  console.log(this.name);
};

console.log("sayName" in person1);      // false

person1.name = "Greg";
console.log(person1.name);            // "Nicholas"

delete person1.name;
console.log("name" in person1);        // true
console.log(person1.name);            // "Nicholas"

var descriptor = Object.getOwnPropertyDescriptor(person1, "name");
console.log(descriptor.configurable);    // false
console.log(descriptor.writable);       // false