ECMAScript Obejct 属性操作API

Object

创建对象

我们有很多种方法创建一个对象,Object.create, Object.assign

Object.create

//字面量
var o = {};
// 等同于
var o = Object.create(Object.prototype)

// 字面量创建对象,建立属性
var obj = {name: "hello"};
// 等同于
var obj = Object.create(Object.prototype, {
	name: {writable:true, configurable:true, value: "hello" }
})

// 构造器创建对象
var Obj = function() {
  this.name = "hello";
}
var obj = new Obj;
// 等同于使用Obj的原型链创建
var obj = Object.create(Obj.prototype, {
	name: {writable:true, configurable:true, value: "hello" }
})

obj.__proto__ == Obj.prototype // true

Object.assign

Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象身上,该方法使用源对象的 [ [ Get ] ] 和目标对象的 [ [ Set ] ],所以它会调用相关 getter 和 setter。因此,它分配属性而不是复制或定义新的属性。

语法

Object.assign(target, ...sources)

测试

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。

所以对待浅拷贝我们一般使用这样的形式

var obj = Object.assign({}, o1, o2, o3);

继承属性和不可枚举属性是不能拷贝的

var obj = Object.create({foo: 1}, { // foo 是个继承属性。
    bar: {
        value: 2  // bar 是个不可枚举属性。
    },
    baz: {
        value: 3,
        enumerable: true  // baz 是个自身可枚举属性。
    }
});

var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

对象属性增删改

属性有几个特性:

  • configurable : 当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false。configurable 特性表示对象的属性是否可以被删除,以及除 writable 特性外的其他特性是否可以被修改。
  • enumerable: 当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false。
  • value : 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined
  • writable: 当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false
  • get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined
  • set :一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined

创建属性 Object.defineProperty

var o = {};

Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true
});

// 数据描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", {
  value: 0x9f91102, 
  get: function() { 
    return 0xdeadbeef; 
  } 
});

修改属性 Object.defineProperty

如果描述符的 configurable 特性false(即该特性为non-configurable),那么除了 writable 外,其他特性都不能被修改,并且数据和存取描述符也不能相互切换。

var o = {};

Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : false
});

Object.defineProperty(o, "a", {enumerable : false}) //TypeError: Cannot redefine property: a

设置多个属性 Object.defineProperties

使用 Object.defineProperties 设置多个属性

var obj = {};
Object.defineProperties(obj, {
  "property1": {
    value: true,
    writable: true
  },
  "property2": {
    value: "Hello",
    writable: false
  }
  // 等等.
});

冻结对象 Object.freeze

Object.freeze() 方法可以冻结一个对象,浅冻结,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。

冻结对象的所有自身属性都不可能以任何方式被修改。任何尝试修改该对象的操作都会失败,可能是静默失败,也可能会抛出异常(严格模式中)。

var obj = {name:"hello"}

Object.isFrozen(obj) // false
Object.freeze(obj)
Object.isFrozen(obj) // true

obj.name = "hello2" // 严格模式抛错
obj.name = "hello" // freeze

浅冻结

冻结的属性是不能修改的,但是引用的对象是可以修改的。冻结只是冻结对象的属性

var obj = {
  name:"hello", 
  internal: {
    name: "internal"
  }, 
  internalFunc: function(){
    console.log("internal function")
  }
}

Object.freeze(obj)
obj.internal.name = "after freeze"
obj.internalFunc = function() {
  console.log("after freeze")
}

console.log(obj.internal.name) // after freeze
obj.internalFunc() // internal function

对象属性遍历

for...in 循环只遍历可枚举属性。像 Array 和 Object 使用内置构造函数所创建的对象都会继承自 Object.prototype 和 String.prototype 的不可枚举属性,例如 String indexOf() 方法或者 Object 的 toString 方法。

var obj = Object.create({
  name: "kk",
  nick: "kkj"
}, {
  age: {writable:true, configurable:true, value: 27, enumerable: true }
});

for(let key in obj){
  console.log(key); // age, name, nick
}

hasOwnProperty

可以使用对象的原型链上的hasOwnProperty 方法判断对象是否具有指定的属性作为自身(不继承)属性。

var obj = Object.create({
  name: "kk",
  nick: "kkj"
}, {
  age: {writable:true, configurable:true, value: 27, enumerable: true },
  sex: {writable:true, configurable:true, value: 'male', enumerable: false}
});

for(let key in obj){
  if(obj.hasOwnProperty(key)){
    console.log(key); // age
  }
}

这里因为 sex 不可枚举,所以在 for…in 中没有遍历出来,如果

obj.hasOwnProperty("sex") // true

getOwnPropertyNames

返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性)组成的数组。

var obj = Object.create({
  name: "kk",
  nick: "kkj"
}, {
  age: {writable:true, configurable:true, value: 27, enumerable: true },
  sex: {writable:true, configurable:true, value: 'male', enumerable: false}
});

Object.getOwnPropertyNames(obj) // ["age", "sex"]

Object.key

返回一个由给定对象的自身 可枚举属性 组成的数组

var obj = Object.create({
  name: "kk",
  nick: "kkj"
}, {
  age: {writable:true, configurable:true, value: 27, enumerable: true },
  sex: {writable:true, configurable:true, value: 'male', enumerable: false}
});

Object.keys(obj) // ["age"]

Object.values

返回一个给定对象自己的所有可枚举属性值的数组

var obj = Object.create({
  name: "kk",
  nick: "kkj"
}, {
  age: {writable:true, configurable:true, value: 27, enumerable: true },
  sex: {writable:true, configurable:true, value: 'male', enumerable: false}
});

Object.values(obj) // [27]

getOwnPropertyDescriptor

返回指定对象上一个自有属性对应的属性描述符。

var obj = Object.create({
  name: "kk",
  nick: "kkj"
}, {
  age: {writable:true, configurable:true, value: 27, enumerable: true },
  sex: {writable:true, configurable:true, value: 'male', enumerable: false}
});

Object.getOwnPropertyDescriptor(obj, "name") // undefined
Object.getOwnPropertyDescriptor(obj, "nick") // undefined
Object.getOwnPropertyDescriptor(obj, "age") //  {value: 27, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(obj, "sex") //  {value: "male", writable: true, enumerable: false, configurable: true}

getOwnPropertyDescriptors

用来获取一个对象的所有自身属性的描述符。

var obj = Object.create({
  name: "kk",
  nick: "kkj"
}, {
  age: {writable:true, configurable:true, value: 27, enumerable: true },
  sex: {writable:true, configurable:true, value: 'male', enumerable: false}
});

Object.getOwnPropertyDescriptors(obj)

{
  "age": {
    "value": 27,
    "writable": true,
    "enumerable": true,
    "configurable": true
  },
  "sex": {
    "value": "male",
    "writable": true,
    "enumerable": false,
    "configurable": true
  }
}

原型

getPrototypeOf

返回指定对象的原型

let proto = {};
let obj = Object.create(proto);

Object.getPrototypeOf(obj) === proto; // true

isPrototypeOf

isPrototypeOf 和 instanceof operator 是不一样的。在表达式 object instanceof AFunction 中,检测的是AFunction.prototype 是否在object 的原型链中,而不是检测 AFunction 自身。

let proto = {};
let obj = Object.create(proto);

proto.isPrototypeOf(obj) // ture
posted @ 2017-05-07 21:14  buzzjan  阅读(312)  评论(0编辑  收藏  举报