Javscript 对象

发表于: 2015-08-28分类于:JavaScript

检测对象

  • in 这个关键字检测一个属性是否在某个对象上
  • hasOwnPreperty 这个方法判断一个对象的自有属性中是否包含某个属性
  • propertyIsEnumerable 这个方法判断某个属性是否可以枚举而且这个属性需要是自身属性
  • getOwnPropertyNames 这个方法获得对象所有自身属性的名称

属性的可枚举性

以下几个操作会忽略 enumerable 为 false 的属性

  • for...in 循环:只遍历对象自身的和继承的可枚举的属性
  • Object.keys():返回对象自身的所有可枚举的属性的键名
  • JSON.stringify():只串行化对象自身的可枚举的属性
  • Object.assign():会忽略 enumerable 为 false 的属性,只拷贝对象自身的可枚举的属性

属性的遍历

  • for…in

for…in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。

  • Object.keys(obj)

Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)。

  • Object.getOwnPropertyNames(obj)

Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)。

  • Object.getOwnPropertySymbols(obj)

Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性。

  • Reflect.ownKeys(obj)

Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管是属性名是Symbol或字符串,也不管是否可枚举。

这部分内容摘自:http://es6.ruanyifeng.com/#docs/object

getter 和 setter

对象直接量

var o = {
    $n:0,
    get next(){return this.$n++;},
    set next(value){
        if(this.$n < value){
            this.$n = value;
        }
    }
};

console.log(o.next); // 0
console.log(o.next); // 1

这样这个对象就有了一个属性 next,看起来很奇怪,但是确实是这样,他并不是一个函数,而是一对 getter 和 setter,对这个属性的读取设置将会有get和set函数处理。需要注意的是,上面代码中的 this 值,这个 this 指代对象本身

数据属性有4个特性分别是他的的值,以及是否可以写,是否可以枚举,是否可以配置。

而存取器属性不具有值和可写性,他的4个特性是 读取,写入,可枚举性,和可配置性。

我为了能够查看这些特性,可以使用Object.getOwnPropertyDescriptor(Object, prop)方法,第一个参数为对象,第二个是对象的一个属性。

有读取自然就有设置,为此 可以使用 Object.defineProperty(Object, prop, descriptor)

用法如下:

var GG = new Person();
Object.defineProperty(GG, 'age', {
    value:20,
    writable:true,
    enumrable:true,
    configurable:true
});

定义的时候不需要包含全部4项,没有明确写出来的就是 undefined(特指 value 特性) 或者 false

通过对象字面量比如:

var o = {
    type:'text'
}

这个时候他的 value 是 ‘text’ 其他三项都为 true

原型属性

  • 对象直接量的原型:Object.prototye
  • 使用 new 创建的对象:构造函数的 prototype 属性
  • Object.create 创建的对象使用第一个参数作为其原型

可以使用 getPrototypeOf 查询一个对象的原型

想要检验一个对象是否为另一个对象的原型,可以使用 isPrototypeOf 来检测

es6 扩展

属性的简洁表示法

var a = 12;
var fun1 = function(){}
var obj = {
    a,
    fun1,
    fun2(){
        console.log(this.a);
    }
};

// 等同于
var obj = {
    a:a,
    fun1:fun1,
    fun2:function(){
        console.log(this.a);
    }
};

属性名表达式

对于对象字面量,javascript 之前只能使用字符串作为属性名,不能使用变量,使用变量则需要在外面使用 [] ,现在可以了

var obj = {
    ['a' + 1](){
        console.log('a1');
    }
}

obj.a1(); // 'a1'

Object 的静态方法

hasOwnProperty

判断对象的是否有一个属性存在在它自身上,而不是存在在 原型上。

var o = {x:1};
o.hasOwnProperty("x");  // true
o.hasOwnProperty("y");  // false
o.hasOwnProperty("toString");  // false

propertyIsEnumerable

判断对象的某个属性是否存在在其自身上,而且可以枚举。

function Person(name,age){
    this.age = age;
    this.name = name;
}

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


var p = new  Person("jack",22);

console.log(p.propertyIsEnumerable("age")); // true
console.log(p.propertyIsEnumerable("sayName"));  // false

isPrototypeOf

判断一个对象是不是另一个对象的原型

function app(name,version){
    this.name = name;
    this.version = version;
}
app.prototype.platform = "Linux";

var test = new app("test","0.1");

console.log(app.prototype.isPrototypeOf(test));

Object.keys

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

Object.getOwnPropertyNames

返回对象自身的所有属性(包括不可枚举的属性)

Object.getOwnPropertyDescriptor

返回对象的自身某个属性(不包含原型链)的属性对象(writable,value,enumerable,configurable,get,set 等)

Object.getOwnPropertySymbols

Object.getOwnPropertySymbols方法返回一个数组,成员是当前对象的所有用作属性名的Symbol值。

Object.defineProperty

给对象定义一个属性,只有通过这个方式才能自定义对象属性的属性。

var random = {};

Object.defineProperty(random, "int8", {
    get:function(){
        return Math.floor(Math.random()*256-128);
    },
    configurable:false,
    enumerable:true
});

Object.defineProperties

如果希望一次性定义多个属性,可以使用这个方法

var random = {};

Object.defineProperties(random,{
    int8:{
        get:function(){
            return Math.floor(Math.random()*256-128);
        },
        configurable:false,
        enumerable:true
    },
    uint8:{
        get:function(){
            return Math.floor(Math.random()*256);
        },
        configurable:false,
        enumerable:true
    }
});

以上这两个方法有一些规则如下:(摘抄于《JavaScript 权威指南 英文版》)

  • If an object is not extensible, you can edit its existing own properties, but you cannot add new properties to it.
  • If a property is not configurable, you cannot change its configurable or enumerable attributes.
  • If an accessor property is not configurable, you cannot change its getter or setter method, and you cannot change it to a data property.
  • If a data property is not configurable, you cannot change it to an accessor property.
  • If a data property is not configurable, you cannot change its writable attribute from false to true , but you can change it from true to false .
  • If a data property is not configurable and not writable, you cannot change its value. You can change the value of a property that is configurable but nonwritable, however (because that would be the same as making it writable, then changing the value, then converting it back to nonwritable).

Object.setPrototypeOf

对象中存在一个 __proto__ 属性,这个属性是对象的原型,这并不是标准,但是很多浏览器都是这样实现的,但是推荐还是不要直接去操作这个属性,而是使用 Object.setPrototypeOf 这个方法

function Person(name){
    this.name = name;
}

Person.prototype.getName = function(){
    return this.name;
}

var zhang = {
    name:'zhang'
};

Object.setPrototypeOf(zhang, Person.prototype);

console.log(zhang.getName());

Object.getPrototypeOf

得到一个对象的原型

Object.preventExtensions

使一个对象不能再扩展。一旦对象被设置成不可扩展,就不能在修改为可以扩展了。另外,不可扩展仅仅是指对象本身不可扩展,如果其原型可以扩展,还是可以在原型上添加属性的。

var test = {};
Object.preventExtensions(test);
test.id = 123;   // 在严格模式下,会抛出错误;在非严格模式下,会被忽略。

Object.isExtensible

判断一个对象是否能被扩展。

Object.seal

使得一个对象不可扩展,设置所有属性的 configurable 为 false。

Object.isSealed

可以判断一个对象是否处于 seal 的状态

Object.freeze

使对象不可扩展,而且所有属性为只读。对于有 set 方法的存取器属性,还是可以用 set 方法写数据。

Object.isFrozen

检验是否处于 frozen 状态。

Object.create

创建一个拥有指定原型和若干个指定属性的对象。第一个参数会作为创建的对象的原型,第二个参数的形式同 ‘defineProperties’ 的第三个参数

function Person(name){
    this.name = name;
}

Person.prototype.getName = function(){
    return this.name;
}

var wang = Object.create(Person.prototype,{
    name:{
        value:'wang',
        writable:true,
        enumerable:true,
        configurable:true
    }
});

var name = wang.getName(); // 'wang'

Object.is

这个静态方法用来判断两个值是否相等,对于传统的使用 === 来比较两个值是否相等的做法存在两个问题:

  1. 0 === -0 为 true
  2. NAN === NAN 为 false

而 Object 解决了这一点,其他方面与 === 一致

Object.assign

该方法用于对象的合并,将源对象的所有可枚举的属性复制到目标对象,不拷贝继承的属性

var obj1 = {
    a:1
};
var obj2 = {
    b:2
};
var obj3 = Object.assign({}, obj1, obj2);
console.log(obj3); // { a: 1, b: 2 }