Object refers to a data structure containing data and instructions for working with the data.--MDN 上的定义
知识点一:创建对象的方法
一:对象直接量
名值对映射表创建
名是可为空字符串,但是不能两个字符串相同,值可为任意值
逗号在不同规范中的使用
对象直接量的计算
二:关键字new 创建并初始化一个新对象
1.原始类型中的内置构造函数创建对象
2.自定义构造函数来初始化新对象(很常见)
3.上述两种构造函数都是需要和new一起使用来创建
三:Object.create()
第一个参数是这个对象的原型
第二个参数可选
是一个静态函数,而不是被调用的方法
此方法是ECMAscript5(E5)中使用,在ECMAscript3(E3)中使用inherit()模拟这个方法但不是完全功能相同,同时inherit()还能防止库函数的恶意修改( ?)
知识点二:原型 (按照创建方法分类)
1.对象直接量创建的对象都具有同一个原型对象,可以通过Object.prototype获得对原型对象的引用
2.通过new创建的对象,原型就是构造函数的prototype属性的值
3.内置构造函数的已经大部分自定义的构造函数都具有一个继承自Object.prototype的原型
4.通过new Date()创建的Date对象的属性继承自Date.prototype,而Date.prototype又继承自Object.prototype,这一系列原型对象构成了所谓的原型链。
5.通过Object.create()创建的对象,第一个参数就是整个对象的原型
6.没原型的对象很少,Object.prototype就是一个
小结:创建一个空对象的方法:let o=Object.create(Object.prototype);/{/empty/};/new Object();
知识点三:对象的三个属性
1.原型属性:对象的原型属性是用来继承属性的,“o的原型属性”直接叫做“o的原型”
1.1 原型属性(原型)按照创建对象的方法大致分类
{}方法创建的实例,实例的原型属性(或原型)是Object.prototype
new方法创建的实例,实例的原型属性(或原型)是构造函数的prototype属性
Object.create()方法创建的实例,实例的原型属性(或原型)是第一个参数(可为null)
对象直接量和Object.create()创建的实例都包含一个constructor属性,这个属性指代Object()构造函数,因此constructor.prototype才是对象直接量的真正属性,而Object.create()则往往不是(?)
1.2原型的查询方式
E5中将对象作为参数传入Object.getProtypeOf()查询
E3中使用表达式o.constructor.prototype来检测,
检测一个对象是否为另外一个的原型(或处于原型链中)使用isPrototypeOf()
2.类属性
2.1类属性的定义和查询方法
对象的类属性表示对象的类型信息,是一个字符串。
默认查询类属性方法是继承与Object.prototype的toString()方法,返回的结果为[object class]
因为对象继承的toString()被重写,必须间接调用Function.call();书中定义了一个classof()方法来实现查询类属性。
类属性的分类(依据对象创建的方式)
内置构造函数(如:Array、Date)创建的对象,类属性与构造函数名称匹配
宿主对象也包括有类属性,与具体实现有关
对象直接量、Object.create()和自定义构造函数创建的对象其类属性都是"Object"
3.对象的可扩展性
可扩展性用来表示是否可以给对象添加新属性
在ES3和ES5中所有内置对象和自定义对象都是可扩展的,宿主对象的可扩展性是由js引擎定义的
Object.esExtensible()可以判断对象是否可扩展
Object.preventExtensions()可以将对象作为参数传入转换为不可扩展,并且无法逆转,次函数只影响对象本身,对象的原型添加属性该可不扩展的对象同样会继承这个新属性
Object.seal()是上面函数的加强版,还可以将对象的自有属性设置为不可配置,同时已有属性无法删除或配置,但是已有的可写属性依然可以设置,不可逆转,检测是否封闭的函数Object.issealed()
Object.freeze是seal()的加强版,除了上述特性还可以将它的自有的所有数据属性设置为只读,但是对象的存储器属性具有setter方法,存取器属性将不受影响,仍可以通过属性赋值调用。检测是否冻结的函数Object.isFrozen();
知识点四:属性的查询、继承、设置、删除、检测和枚举
属性的查询
查询方法一(.)
(.)右侧必须是一个属性名称命名的简单标识符
E3中标识符不能为保留字,如果为保留字必须使用[]来访问
E5中可以使用保留字
查询方法二[ ]
- 方括号内必须是一个可以转化为字符串的表达式
两种查询方法的异同
两种方法都可以给对象创建属性或者给属性赋值
点运算符因为要求属性名是标识符,不是一个数据类型,程序在运算中无法动态的修改一一个标识符
而[]在运算中的属性名是一个字符串可以动态的修改,更常用
属性的继承
1.js重要特征:查询属性时才会考虑继承的存在,设置属性和继承无关
2.为对象o的属性X赋值,有以下几种情况
2.1.o中已经有属性x且不是继承而来,此时赋值只改变属性x的值
2.2.如果o不存在属性x,那么赋值会添加一个新属性x
2.3.如果之前o继承自属性x,这个继承的属性就被新创建的同名属性覆盖
2.4.如果o继承的x是只读的,赋值不允许执行
2.5.o继承属性x是一个具有setter方法的accessory属性,此时o会调用setter方法,此方法定义的任意属性只针对o本身
属性的访问错误
1.查询一个对象不存在的属性返回undefined,不报错,如果对象也不存在就报错
2.在ES5的'use strict'下,任何失败的属性设置操作都抛出一个类型错误异常
3.o的属性p是只读的,则不能重新赋值,但是defineProperty()方法可以为可配置的只读属性重新赋值
4.o的属性p继承的,且是只读,赋值的覆盖操作不允许
5.如果o不存在p,且无setter方法可以调用,则p一定会添加到o中
6.如果o是不可扩展的,则o不能定义新属性
小结:属性访问的两种方式:查询一个值或者是设置一个值,
属性的删除 特点总结
1.使用delete运算符
2.操作数应该是一个属性访问表达式
3.此运算符只是切断了属性和宿主对象的练习,不会操作属性中的属性,这种删除属性的引用的存在很可能造成内存泄露(?),所以销毁一个对象,必须遍历属性中的属性一次删除
4.只能删除自有属性,不能删除继承属性
5.delete删除成功或者删除不存在的属性都会返回true
6.严格模式delete一个不可配置的属性会报类型错误,非严格模式和ES3中,这些情况的delete操作会返回false;严格模式中,如果后面是一个非法操作数会报语法错误
7.非严格模式中删除全局对象的可配置属性,可以省略对全局对象的引用。
检测属性
1.in运算符:被检测属性被包含在自有属性和继承属性中就返回true,如果被检测属性需要判断是否是undefined,使用"!=="来判断
2.对象的hasOwnProperty()方法用来判断属性是否是自有属性,其余属性返回false
3.如果被检测属性是自有属性同时满足是可枚举性,方法propertyIsEnumerable()才会返回true,其余是false
枚举属性
1.ES3中枚举属性的方法:使用for/in循环和if语句加上检测属性的各种方法我们可以枚举到自己需要的属性这些自己写的函数主要使用在ES3中
2.ES5中枚举属性的方法:Object.keys()返回的数组由对象中自有属性的可枚举属性构成;Object.getOwnPropertyNames()返回的是的所有的自有属性,不仅是可枚举属性
知识点五:属性的特性、getter和setter方法
属性的getter和setter方法
1.属性分为数据属性和存取器属性,数据属性只有一个简单的值,
2.属性值可以用一个或两个方法替代,这两个方法就是getter和setter方法,由两者定义的属性称作存取器属性
3.返回值和参数:查询存取器属性的值,js调用getter方法(无参数),返回值就是属性存取表达式的值;当程序设置一个存取器属性的值时,js调用setter方法,将赋值表达式右侧的值当做参数传入setter,可以忽略setter方法的返回值
4.存取器属性不具有可写性,一个属性两种方法都具备此属性是一个读/写属性,只有getter方法就是只读属性,只有setter方法,致谢属性(数据属性中有例外?),读取只写属性总是返回undefined
属性的特性
属性特性的定义
0.每个属性都包含一个名字,四个特性
1.数据属性的四个特性: 值value,可写性writable,可枚举性enumerable,可配置性configurable
2.存取器属性的四个特性:读取get,写入set,可枚举性enumerable,可配置性configurable
特性的操作
3.为了定义属性特性的方便,js为属性的四个特性专门定义了一个对象:属性描述符(property descriptor),此对象的属性和它所描述的属性特征是同名的。
4.通过调用Object.getOwnPropertyDescriptor(object,"property")来获取属性的property descriptor,继承属性的获取方法Object.getPrototypeOf()
5.设置属性特性的方法是,Object.definePeoperty(object,"property",{property descriptor})
6.设置属性特性不必包含所有四个特性,新建属性的默认值是false和undefined,修改的已有属性,默认的特性值没有任何修改,继承属性不能修改
属性的新建和修改规则
7.如果对象是不可扩展的,只能编辑已有自有属性,不能添加属性
8.如果存取器属性是不可配置,a:不能修改getter和setter方法,b:不能转换为数据属性,c:不能修改配置型和枚举性,d,属性也不能删除
9.如果数据属性是不可配置的,a:不能转化成存取器属性,b:可写性不能从false修改成true,反过来可以,c:同时不可写,则不能修改它的值,d:可配置,不可写的值可以修改,e:不能修改配置型和枚举性,f,属性也不能删除
序列化对象
定义
1.对象的序列化是指将对象的状态转换为字符串
方法
2.JSON.stringify()JSON.parse()用来序列化和还原js对象
3.这两个方法使用JSON作为数据交换格式
4.JSON的语法是js语法的子集,并不能表示js里面所有的值,可以表示的值:对象,字符串,无穷大,true,false,null
对象的方法
1.大部分js对象都会从Object.prototype继承属性,这些继承的属性主要是方法,也就是对象的方法
2.在类和模块的章节中对对象的方法更为深入的探讨
3.toString(),toLocaleString(),toJSON(),valueOf()方法
setter方法的使用,第六章一句话都没说,真尴尬我都不知道如何用,属性的枚举用for/if写了那么多ES3的方法,就第一个我实验,通过了,后面的都是卡在if读给我false的结局,坑爹,对象的方法本来是很重要的存在,结果一页半的纸张结束了,json数据格式好像也没有重视起来,还有就是那么多的内置方法竟然没有一个统一的整理总结,这几点呢都是需要后面继续补的内容。