JavaScript系列之对象

1.建立对象
(1)对象直接量,每次计算对象直接量的时候,也都会计算它的每一个属性的值。
(2)经过new建立对象,new运算符建立并初始化一个新对象。JavaScript语言核心中原始类型都包含内置构造函数。javascript

每个JavaScript对象(null除外)都和另外一个对象相关联。每个对象都从原型继承属性。
多用经过对象直接量建立的对象都具备同一个原型对象,并能够经过JavaScript代码Object.prototype得到对原型对象的引用。
没有原型的对象为数很少,Object.prototype就是其中之一。它不继承任何属性,其余原型对象都是普通对象,普通对象都具备原型。全部的内置构造函数都具备一个继承自Object.prototype的原型。java

Object,create()第一个参数是这个对象的原型,第二个可选参数,用以对对象的属性进行进一步描述。
能够经过传入参数null来建立一个没有原型的新对象,经过这种方式建立的对象不会继承任何东西。
若是想建立一个普通的空对象,须要传入Object.prototype数组

function inherit(p){
    if(p==null) throw TypeError();
    if(Object,create)
    return Object,create(p);
    var t=typeof p;
    if(t!=='object' && t!=='function')throw TypeError();
    function f(){};
    f.prototype=p;
    return new f();
}

new的底层原理app

function A(x,y){this.x=x;this.y=y}
var a=new A(1,2);

var a=new Object();
a.__proto__=A.prototype;
var r=A.apply(a,arguments);
if(typeof r == 'object')return r;
return a;

2.属性的查询和设置
当使用方括号是,方括号内的表达式必须返回字符串。更严格地讲,表达式必须返回字符串或返回一个能够转换为字符串的值。
JavaScript对象都是关联数组。
属性赋值操做首先检查原型链,以此判断是否容许赋值操做。
若是容许属性赋值操做,它也老是在原始对象上建立属性或对已有的属性赋值,而不会去修改原型链。
在JavaScript中,只有在查询属性是才会体会到继承的存在,而设置属性则和继承无关。函数

查询一个不存在的属性并不会报错,可是,若是对象不存在,那么试图查询这个不存在的对象的属性就会报错。null和undefined值都没有属性,所以查询这些值的属性会报错。固然,给null和undefined设置属性也会报类型错误。给其余值设置属性也不老是成功,有一些属性是只读的,不能从新赋值,有一些对象不容许新增属性,这些设置属性的失败操做不会报错。this

在这些场景下给对象o设置属性p会失败:
o中的属性p是只读的:不能给只读属性从新赋值(defineProperty()方法中有一个例外,能够对可配置的只读属性从新赋值)。
o中的属性p是继承属性,且它是只读的:不能经过同名自有属性覆盖只读的继承属性。
o中不存在自有属性p:o没有使用setter方法继承属性p,而且o的可扩展性是false。若是o中不存在p,并且没有setter方法可供调用,则p必定会添加至o中。但若是o不是可扩展的,那么在o中不能定义新属性。prototype

3.删除属性
delete只是断开属性和宿主对象的联系,而不会去操做属性中的属性。
delete运算符只能删除自有属性,不能删除继承属性。
当delete表达式删除成功或没有任何反作用(好比删除不存在的属性)时,它返回true。若是delete后不是一个属性访问表达式,delete一样返回true。
delete不能删除那些可配置性为false的属性。某些内置对象的属性是不可配置的,好比经过变量声明和函数声明建立的全局对象的属性。
var x=1;//声明一个全局变量
delete this.x;//不能删除这个属性code

this.x=1;//建立一个可配置的全局属性
delete this.x;对象

4.检测属性
in运算符的左侧是属性名(字符串),右侧是对象。若是对象的自有属性或继承属性中包含这个属性则返回true。
对象的hasOwnProperty()方法用来检测给定的名字是不是对象的自有属性。对于继承属性它将返回false。
propertyIsEnumerable()是hasOwnProperty()的加强版,只有检测到自有属性且这个属性的可枚举性为true时它才返回true。某些内置属性是不可枚举的。一般又JavaScript代码建立的属性都是可枚举的。
!==判断一个属性是不是undefined
in能够区分不存在的属性和存在但值为undefined的属性。继承

5.枚举属性
for/in循环能够在循环体中遍历对象全部可枚举的属性(包括自有属性和继承的属性),把属性名称赋值给循环变量。对象继承的内置方法不可枚举的,但在代码中给对象添加的属性都是可枚举的。
Object.keys(),它返回一个数组,这个数组由对象中可枚举的自有属性的名称组成。
Object.getOwnPropertyNames(),它返回一个数组,这个数组由对象中全部自有属性的名称组成。

6.属性getter和setter
和数据属性不一样,存取器属性不具备可写性。若是属性同时具备getter和setter方法,那么它是一个读/写属性。若是它只有getter方法,那么它是一个只读属性。若是它只有setter方法,那么它是一个只写属性(数据属性中有一些例外),读取只写属性老是返回undefined。
和数据属性同样,存取器属性是能够继承的。

数据属性的4个特性分别是它的值(value)、可写性(writable)、可枚举性(enumerable)和可配置性(configurable)。
存取属性不具备值特性和可写性,它们的可写性是由setter方法存在与否决定的。
存取器属性的4个特性是读取(get)、写入(set)、可枚举性和可配置性。

为了实现属性特性的查询和设置操做,ECMAScript5中定义了一个名为“属性描述符”的对象,这个对象表明那4个特性。描述符对象的属性和它们所描述的属性特性是同名的。
经过调用Object.getOwnPropertyDescriptor()能够得到某个对象特定属性的属性描述符。该方法只能获得自有属性的描述符,要想得到继承属性的特性,须要遍历原型链。获取原型的方法是Object.getPrototypeOf()

要想设置属性的特性,或者想让新建属性具备某种特性,则须要调用Object.defineProperty(),传入要修改的对象、要建立或修改的属性的名称以及属性描述符对象。
传入Object.defineProperty()的属性描述符没必要包含全部4个特性。对于新建立的属性来讲,默认的特性值是false或undefined。
若是要同时修改或建立多个属性,则须要使用Object.defineProperties()。第一个参数是要修改的对象,第二个参数是一个映射表,它包含要新建或修改的属性的名称,以及它们的属性描述符。

对于那些不容许建立或修改的属性来讲,若是用Object.defineProperties()和Object.defineProperty()对其操做(新建或修改)就会抛出类型错误异常。
若是对象是不可扩展的,则能够编辑已有的自身属性,但不能给它添加新属性。
若是属性是不可配置的,则不能修改它的可配置性和可枚举性。
若是存取器属性是不可配置的,则不能修改器getter和setter方法,也不能将它转换为数据属性。
若是数据属性是不可配置的,则不能将它转换为存取器属性。
若是数据属性是不可配置的,则不能将它的可写性从false修改成true,但能够从true修改成false。
若是数据属性是不可配置且不可写的,则不能修改它的值。然而可配置但不可写属性的值是能够修改的。

7.对象的三个属性
对象的原型属性是用来继承属性的。
要检测一个对象是不是另外一个对象的原型(或处于原型链中),请使用isPrototypeOf()方法。
在ECMAScript5中,将对象做为参数传入Object.getPrototypeOf()能够查询它的原型。

对象的类属性

function classof(){
    if(o===null)return 'Null';
    if(o===undefined)return 'Undefined'
    return Object.prototype.toString.call(o).slice(8,-1)
}

可扩展性
全部内置对象和自定义对象都是显式可扩展的,宿主对象的可扩展性是由JavaScript引擎定义的。
ECMAScript5定义了用来查询和设置对象可扩展性的函数。经过将对象传入Object.isExtensible(),来判断对象是否可扩展的。若是想将对象转换为不可扩展的,须要调用Object.preventExtensions(),将待转换的对象做为参数传进去。
一旦将对象转换为不可扩展的,就没法再将其转回回可扩展的了。preventExtensions()只影响到对象自己的可扩展性。若是给一个不可扩展的对象的原型添加属性,这个不可扩展的对象一样会继承这些新属性。

可扩展属性的目的是将对象“锁定”,以免外界的干扰。

Object.seal()可以将对象设置为不可扩展的,还能够将对象的全部属性都设置为不可配置的。对于已经封闭起来的对象是不可解封的,可使用Object.isSealed()来检测对象是否封闭。
Object.freeze()可以将对象设置为不可扩展的,还能够将对象的全部属性都设置为不可配置的,同时将它自有的全部数据属性设置为只读。(若是对象的存取器属性具备setter方法,存取器属性将不受影响,仍能够经过给属性赋值调用它们)。使用Object.isFrozen()来检测对象是否冻结。

8.JSON语法是JavaScript语法的子集,它并不能表示JavaScript里的全部值。
支持对象、数组、字符串、无穷大数字、true、false和null,而且它们能够序列化和还原。NaN、Infinity和-Infinity序列化的结果是null,日期对象序列化的结果是ISO格式的日期字符串。函数、RegExp、Error对象和undefined值不能序列化和还原。JSON.stringify()只能序列化对象可枚举的自有属性。对于一个不能序列化的属性来讲,在序列化后的输出字符串中会将这个属性省略掉。

JSON的全称是javascript Object Notation,JavaScript对象表示法。

相关文章
相关标签/搜索