先来看看数据类型中对象的定义。引用类型的值(对象)是引用类型的一个实例。注意,本文讨论的对象与类中的对象不同。
一、语法
对象通过两种形式来定义,声明(文字)类型和new构造形式。
(1)对象字面量表示法。声明对象的简写方式。
var obj={ key:value, name:'liangzai' //... }
(2)new操作符后面跟object构造函数。
var myobj=new Object(); myobj.key=value;
二、类型
js的内置类型;String、Number、Boolean、Object、Function、Array、Date、RegExp、Error。
在js中,实际上这些内置类型是只是一些内置函数。这些内置函数可以当作构造函数来使用,从而可以构造一个对应子类型的新对象。
看以下代码
var str="I am string"; console.log(str.length);//11 console.log(str.charAt(0)) //I
由字面量定义的字符串上可以访问属性和方法,是因为js引擎自动会把字面量转成String对象,所以可以访问属性和方法。
需注意的是,new和undefined没有对应的构造形式,它们只有文字形式,相反,Date只有构造,没有文字形式。
三、内容
对象的内容是由一些存储在特定命名位置的值组成的,也就是属性。需注意一点,对象的内容一般不会存在对象容器内部,存储在对象容器内部的是这些属性的名称,它们就像指针一样,指向这些值真正的存储位置。
var obj={ a:2 } console.log(obj.a) console.log(obj['a']);
如果要访问对象中的值,有两种方式,使用.操作符或者[]操作符。 .a语法通常被称为"属性访问"。['a']语法通常被称为"键访问"。
在对象中,属性名永远都是字符串。即使使用数字作为属性名,它首先会被转换为一个字符串。
3.1 可计算属性名
ES6中增加了可计算属性名。就是通过表达式来计算属性名。
var prefix="foo"; var myobj={ [prefix+'bar']:'hello', } console.log(myobj['foobar']) //hello
3.2属性与方法
访问的对象属性是一个函数,有的人的叫法是方法,因为在类中通常被称为方法。
作者认为在对象中属性如果是函数,“方法”的叫法并不合适。因为对象中对于属性函数的访问,它只是返回一个函数,虽然某些函数有this引用,而this确实会指向调用位置的对象引用,但是本质上并没有把一个函数变成一个方法。
3.3复制对象
深拷贝和浅拷贝
深拷贝:
方法:
var newObj=JSON.parse(JSON.stringfy(someObj));
原理是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象
浅拷贝: object.assign(...)第一个参数是目标对象,之后还可以跟多个源对象。
3.4 属性描述符
var obj={};Object.defineProperty(obj,"a",{ //定义属性value:2,writable:true, //决定是否可以修改属性的值configurable:true,//属性是否可以修改,禁止删掉a这个属性;enumerable:true //是否会出现在对象的属性枚举中 ,即是否会出现在对象的for in循环中})
3.5 不变性
如果想让属性或者对象是不可改变的,有多种方法可以实现。注意的是,所有的方法创建的都是浅不变性。也就是只会影响目标对象和它的直接属性,如果目标对象引用了其他对象(数组、函数等),其他对象的内容不受影响。
1、对象常量
结合writable:false和configurable:false可以创建一个真正的常量属性。(不可修改,重定义或者删除)
2、禁止拓展:
如果想禁止一个对象添加新属性并且保留已有属性。可以使用Object.preventExtensions(...)
var obj={a:2}; Object.preventExtensions(obj); obj.b=3 console.log(obj.b) //undefined
在严格模式下,将会抛出typeError错误。
3、密封
Object.seal(..)会创建一个“密封”的对象,这个方法实际上会在一个现有对象调用Object.preventExtensions(...)并且把所有的属性标记为configurable:false。密封之后,不能添加新属性,也不能重新配置或者删除任何现有属性。
4、冻结
Object.freeze(...)会创建一个冻结对象,这个方法实际上在一个现有对象上调用Object.seal(...)并把所有“数据访问”属性标记为writable:false。
5、Getter和Setter
[[Get]]和[[Put]]可以控制属性值的设置和获取。
对象内置的[[Get]]操作首先在对象中查找是否有名称相同的属性,如果找到就会返回这个属性的值。
6、存在性
var obj={a:2};
console.log('a'in obj) //true console.log(obj.hasOwnProperty('a'))//true
in操作符会检查属性是否存在对象及其[[Prototype]]原型链中。相比之下,Object.hasOwnProperty(...)只会检查属性是否在obj中,不会检查[[Prototype]]原型链。Object.propertyIsEnumberable(...)会检查给定的属性是否直接存在于对象中;
Object.keys(...)会返回一个数组,包含所有可枚举属性;Object.getOwnPropertyNames(...)会返回一个数组,包含所有属性,无论它们是否可枚举。