详解JavaScript中的Object对象

Object是在javascript中三个被大家平时利用的品种,並且JS中的全部目的都以再三再四自Object对象的。虽说大家一直只是轻易地利用了Object对象来存储数据,并未运用到太多别的职能,可是Object对象实际包罗了众多很有用的属性和艺术,非常是ES5日增的秘籍,由此,本文将从最核心的牵线起来,详细表达了Object的常用方法和行使。

幼功介绍

创造对象

先是我们都明白,对象便是一组平时数据和功效的聚众,我们即便用它来效仿大家实际世界中的对象的。那在Javascript中,创制对象的法子一般有二种格局:布局函数和对象字面量。

new布局函数法

var person = new Object();
person.name = "狼狼的蓝胖子";
person.age = 25;

这种措施使用new关键字,接着跟上Object构造函数,再来给目的实例动态加多上不一致的习性。这种办法相对来讲相比烦琐,日常推荐使用对象字面量来创设对象。

对象字面量

对象字面量很好精通,使用key/value的样式直接成立对象,简洁方便。

var person = {
    name: “狼狼的蓝胖子”,
    age: 25
};

这种办法向来通过花括号将对象的属性包起来,使用key/value的方式创设对象属性,各类属性之间用逗号隔断。
只顾:即使是最后叁特性质,后边就不要加逗号,因为在有的旧的浏览器下会报错。

目的实例的习性和章程

无论通过哪类艺术开创了目的实例后,该实例都会具备上面包车型地铁性质和方式,上边将会相继表达。

constructor属性

constructor属性是保存当前指标的布局函数,前边的例证中,constructor保存的正是Object方法。

var obj1 = new Object();
obj1.id = "obj1";
var obj2 = {
    "id": "obj2"
};

console.log(obj1.constructor);//function Object(){}
console.log(obj2.constructor);//function Object(){}

hasOwnProperty(propertyName)方法

hasOwnProperty方法选择四个字符串参数,该参数表示属性名称,用来决断该属性是不是在时下指标实例中,实际不是在目的的原型链中。大家来看望下边这一个例子:

var arr = [];        
console.log(arr.hasOwnProperty("length"));//true
console.log(arr.hasOwnProperty("hasOwnProperty"));//false

在这里个事例中,首先通过定义了一个数组对象的实例arr,大家领略数组对象实际是透过原型链世袭了Object对象,然后全部本人的部分性质,我们经过hasOwnProperty方法判定length是arr本身的习性,而hasOwnProperty是在原型链上的性子。

hasOwnProperty方法能够和for..in结合起来获取对象自身的key。

isPrototypeOf(Object)方法

isPrototype方法选用二个指标,用来判断当前目的是否在传诵的参数对象的原型链上,聊起来有个别抽象,大家来走访代码。

function MyObject() {}
var obj = new MyObject();
console.log(Object.prototype.isPrototypeOf(obj));

咱俩知道MyObject是持续自Object对象的,而在JS中,世襲是经过prototype来贯彻的,所以Object的prototype必定在MyObject对象实例的原型链上。

propertyIsEnumerable(prototypeName)方法

prototypeIsEnumerable用来推断给定的脾性是还是不是能够被for..in语句给枚举出来。看下边代码:

var obj = {
    name: "objName"
}  
for (var i in obj) {
    console.log(i);
}

实行这段代码输出字符串“name”,那就注脚经过for…in语句能够获得obj的name那么些天性,可是大家领略,obj的品质还会有超级多,例如constructor,譬如hasOwnPrototype等等,可是它们并未有被输出,表达那么些属性不能被for…in给枚举出来,能够经过propertyIsEnumerable方法来获取。

console.log(obj.propertyIsEnumerable("constructor"));//false

认清“constructor”是不是足以被枚举,输出false表达不能够被枚举出来。

toLocaleString()方法

toLocalString方法再次来到对象的字符串表示,和代码的进行情形有关。

var obj = {};
console.log(obj.toLocaleString());//[object Object]  

var date = new Date();
console.log(date.toLocaleString());//2016/2/28 下午1:39:27

toString()方法

toString用来回到对象的字符串表示。

var obj = {};
console.log(obj.toString());//[object Object]

var date = new Date();
console.log(date.toString());//Sun Feb 28 2016 13:40:36 GMT+0800 (中国标准时间)

valueOf()方法

valueOf方法重返对象的原始值,也许是字符串、数值或bool值等,看现实的靶子。

var obj = {
    name: "obj"
};
console.log(obj.valueOf());//Object {name: "obj"}

var arr = [1];
console.log(arr.valueOf());//[1]

var date = new Date();
console.log(date.valueOf());//1456638436303

如代码所示,多少个例外的靶子实例调用valueOf重返不一致的数量。

质量的档期的顺序

在Javascript中,属性有两种类型,分别是数据属性和寻访器属性,大家来拜望那二种属性具体是怎么着事物。

多少属性

多少属性我们得以知晓为大家日常定义对象时赋予的性格,它能够打开读和写。可是,ES第55中学定义了部分特征,那一个特点是用来描述属性的各个风味,性子是内部值,不能够直接访谈到。天性通过用两对方括号表示,举个例子[[Enumerable]]。属性的表征会有局地暗中认可值,要改革特性的私下认可值,必需选拔ES5定义的新格局Object.defineProperty方法来改正。

数码属性有4个描述其特点的特色,下边将相继表达每三个风味:

(1)[[Configurable]]:该天性表示是或不是足以因此delete操作符来删除属性,默许值是true。

var obj = {};
obj.name = "myname";

delete obj.name;
console.log(obj.name);//undefined

这段代码很显眼,通过delete删除了obj的name属性后,我们再拜会name属性就会见不到了。

大家透过Object.defineProperty方法来校勘[[Configurable]]特性。

var obj = {};
obj.name = "myname";
Object.defineProperty(obj, "name", {
    configurable: false
})                

delete obj.name;
console.log(obj.name);//myname

通过将configurable天性设置成false之后,delete就不恐怕删除name属性了,假若在严谨格局下,使用delete去删除就能报错。

(2)[[Enumerable]]:表示是还是不是可以透过for…in语句来枚举出属性,暗中同意是true

大家来寻访前边的例子:

var obj = {
    name: "objName"
}  
for (var i in obj) {
    console.log(i);//name
}

这段代码只输出了name属性,大家来将constructor属性的[[Enumerable]]设置为true试试。

var obj = {
        name: "objName"
}
Object.defineProperty(obj, "constructor", {
    enumerable: true
})

for (var i in obj) {
    console.log(i);//name,constructor
}
console.log(obj.propertyIsEnumerable("constructor"));//true

这段代码中,for…in循环获得了name和constructor两本性情,而透过propertyIsEnumerable方法来剖断constructor也回到了true。

(3)[[Writable]]:表示属性值是还是不是足以改善,默感觉true
如果[[Writable]]被安装成false,尝试改正时将从未意义,在严俊格局下会报错

(4)[[Value]]:表示属性的值,默以为undefined

咱俩由此四个简约的例子来会见这三个特色:

var obj = {
    name: "name"
};
console.log(obj.name);//name        

Object.defineProperty(obj, "name", {
    value: "newValue",
    writable: false
})
console.log(obj.name);//newValue

obj.name = "oldValue";
console.log(obj.name);//newValue

咱俩首先定义了obj对象的name属性值为“name”,然后通过defineProperty方法来改进值,并且将其安装为不可改良的。接着大家再改过name属性的值,能够窥见改革无效。

假诺大家透过defineProperty来改正name属性的值,是不是能够纠正呢?答案是足以的:

Object.defineProperty(obj, "name", {
    value: "oldValue"
})
console.log(obj.name); //oldValue

访谈器属性

拜会器属性有一点点相符于C#中的属性,和数量属性的界别在于,它没有数据属性的[[Writable]]和[[Value]]八个性情,而是有着一对getter和setter函数。

[[Get]]:读取属性时调用的函数,默许是undefined
[[Set]]:设置属性时调用的函数,私下认可是undefined

getter和setter是一个很有用的事物,假诺有多少个属性,在那之中第一个属性值会随着第一个属性值的变通而变化。这种地方在我们平昔的编码中初始是老大不足为道的。在早前的做法中,大家频频要去手动矫正第壹脾性情的值,那以往大家就足以通过get和set函数来解决那些标题。看上边那个事例:

var person = {
    age: 10
}

Object.defineProperty(person, "type", {
    get: function () {
        if (person.age > 17) {
            return "成人";
        }
        return "小孩";
    }
})

console.log(person.type);//小孩

person.age = 18;
console.log(person.type);//成人

经过改进age的值,type的值也会相应的改良,这样我们就毫无再手动的去校正type的值了。

上面这种情势也是足以兑现均等的成效:

var person = {
    _age: 10,
    type: "小孩"
} 

Object.defineProperty(person, "age", {
    get: function () {
        return this._age;
    },
    set: function (newValue) {
        this._age = newValue;
        this.type = newValue > 17 ? "成人" : "小孩";
    }
})
console.log(person.type);

person.age = 18;
console.log(person.type);

有关访问器属性,有几点要介意:

1、严苛方式下,必需同有的时候候设置get和set
2、非严酷方式下,能够只设置此中贰个,如若只设置get,则属性是只读的,如若只设置set,属性则无法读取
3、Object.defineProperty是ES5中的新点子,IE9(IE8部分完结,独有dom对象才支撑)以下浏览器不协助,一些旧的浏览器能够透过非规范措施defineGetter()和defineSetter(卡塔尔(قطر‎来安装,这里就不表达了,风乐趣的同校能够寻觅有关材料。

特点操作的相干措施

ES5提供了有的读取或操作属性个性的格局,前边用到的Object.defineProperty就是内部之一。笔者计算了有些相比常用的点子如下:

(1)Object.defineProperty

概念贰个对象的性质,这几个措施后边大家早就应用数次,轻便说说其用法。

Object.defineProperty(obj,propName,descriptor);

defineProperty有一点相似于定于在Object上的静态方法,通过Object直接调用,它选取3个参数:
obj:须求定义属性的指标
propNane:需求被定义的习性名称
defineProperty:属性描述符,包蕴部分质量的特点定义

事举例下:

var obj = {};
Object.defineProperty(obj, "name", {
    value: "name",
    configurable: true,
    writable: true,
    enumerable: true
});

(2)Object.defineProperties

和defineProperty相通,是用来定义对象属性的,差异的是它能够用来还要定义多少个属性,我们经过命名也足以看出来,用法如下:

var obj = {};
Object.defineProperty(obj, {
    "name": {
        value: "name",
        configurable: true,
        writable: true,
        enumerable: true
    },
    "age": {
        value: 20 
    }
});

(3)Object.getOwnPropertyDescriptor

ES5中还提供了二个读取性格值的措施,该办法选用目的及其属性名作为五个参数,重返叁个目的,依据属性类型的差异,重回对象会蕴藏分歧的值。

var person = {
    _age: 10,
    type: "小孩"
}
Object.defineProperty(person, "age", {
    get: function () {
        return this._age;
    },
    set: function (newValue) {
        this._age = newValue;
        this.type = newValue > 17 ? "成人" : "小孩";
    }
})

console.log(Object.getOwnPropertyDescriptor(person, "type"));//Object {value: "成人", writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(person, "age")); //Object {enumerable: false, configurable: false, get: function(),set: function ()}

Object的方法

在ES5中,Object对象上增加生产数量了一堆措施,那么些方法可以一直通过Object进行访谈,后边用到的defineProperty正是增创的诀窍之一。除却还大概有超多艺术,我将其总括归咎如下:

指标创制型方法

Object.create(proto, [propertiesObject])

在前方大家关系,创造叁个目的有三种方法:布局函数和指标字面量。

那二种方法有一个宿疾便是:如若要创设五个对象,写起来很麻烦,所未来来就有了一种创立自定义布局函数的办法来创设对象,如下所示:

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

var person = new Person("Jack", 15);

这种格局可以很有益于的创导多少个一律的对象,也是当前可比常用的办法。

ES5提供的Object.create方法也是一个创制对象的方法,那个艺术允许为成立的靶子选择原型对象,没有必要定义多个布局函数。用法如下:

var obj = Object.create(Object.prototype, { 
    name: {
        value: "Jack"
    }
})
console.log(obj.name);//Jack

以此办法选用的第多个参数作为被创制对象的原型,第二个参数是指标的天性。注意:在此个例子中,name属性是回天乏术被改造的,因为它从不设置writable个性,默许则为false。

私家意见:Object.create这种创立对象的措施略显繁琐,除非是索要矫正属性的特征,不然不提出选取这种方式创立对象。

性子获取型方法

Object.keys

Object.keys是用来博取给定对象的全部可枚举的作者性质的属性名,它回到几个数组。

function Parent() {
    this.lastName = "Black"
}
function Child(firstName) {
    this.firstName = firstName;
}
Child.prototype = new Parent();

var son = new Child("Jack");
console.log(Object.keys(son));//["firstName"]

代码中回到了firstName,并从未回去从prototype世袭而来的lastName和恒河沙数的连锁属性。

在局地旧的浏览器中,大家能够选拔hasOwnProperty和for…in来达成相仿的效果与利益。

Object.keys = Object.keys ||
    function (obj) {
        var keys = [];
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                keys.push(key);
            }
        }
        return keys;
    }

Object.getOwnPropertyNames()

getOwnPropertyNames用来取得对象自己的持有属性,富含可枚举和举不胜举的有所属性,如下所示:

function Parent() {
    this.lastName = "Black"
}
function Child(firstName) {
    this.firstName = firstName;
}
Child.prototype = new Parent();

var son = new Child("Jack");
Object.defineProperty(son, "age", {
    enumerable: false
})
console.log(Object.keys(son));//["firstName"]  
console.log(Object.getOwnPropertyNames(son));//["firstName", "age"]

咱俩定义给son对象定义了叁个数不胜数的性质age,然后通过keys和getOwnPropertyNames八个法子来得到属性列表,能明显看见了两侧分别。

品质性子型方法

以此尤为重假如前方提到的四个章程:defineProperty,defineProperties和getOwnPropertyDescriptor四个艺术

对象节制型方法

ES5中提供了一种类约束对象被改换的不二等秘书籍,用来防止被一些对象被无意修改导致的乖谬。每个约束类型饱含四个决断格局和二个安装方式。

堵住对象增添

Object.preventExtensions(卡塔尔国用来约束对象的增添,设置之后,对象将无法加多新属性,用法如下:

Object.preventExtensions(obj);

该方法接受贰个要被设置成不可能扩大的靶子作为参数,必要静心两点:

1、对象的质量不可用扩大,不过已存在的性质能够被删去
2、不恐怕增加新属性指的是爱莫能助在自个儿上增多属性,假诺是在指标的原型上,还是能加多属性的。

function Person(name) {
    this.name = name;
}
var person = new Person("Jack");
Object.preventExtensions(person);

delete person.name;
console.log(person.name);//undefined

Person.prototype.age = 15;
console.log(person.age);//15

Object.isExtensible方法用来剖断多少个对象是或不是可扩充,暗许情况是true

将目的密闭

Object.seal能够密闭三个对象并回到被密闭的对象。

密闭对象不可能增加或删除原来就有品质,也敬敏不谢改良属性的enumerable,writable,configurable,可是能够改正属性值。

function Person(name) {
    this.name = name;
}
var person = new Person("Jack");
Object.seal(person);
delete person.name;
console.log(person.name);//Jack

将指标密闭后,使用delete删除对象属性,仍然得以访谈获得属性。

透过Object.isSealed能够用来判断一个目的是或不是被密闭了。

结霜对象

Object.freeze方法用来冻结八个对象,被冻结的对象将无法加多,更改,删除属性值,也无可奈何改正属性的性状值,即那几个指标不大概被涂改。

function Person(name) {
    this.name = name;
}
var person = new Person("Jack");
Object.freeze(person);

delete person.name;
console.log(person.name);//Jack

Person.prototype.age = 15;
console.log(person.age);//15

深入分析上边的代码我们可以开采,被冷冻的靶子没办法删除本人的性质,可是经过其原型对象仍然为能够猛增属性的。

透过Object.isFrozen能够用来判别一个目的是或不是被冰冻了。

能够开掘:那八个限定对象的情势的范围程度是逐个上涨的。

总结

Object虽说是贰个大家日常耗费中最平常采纳的对象,可是它的成百上千职能还并未有被大家挖掘出来。本文首先介绍了Object的着力使用,接着介绍了部分超少使用到的脾气性情,最终解析了一部分相比较常用的方式,尤其是ES5中提供的新办法。招待大家调换!!

发表评论

电子邮件地址不会被公开。 必填项已用*标注