对象其实能够看作有许多键值对组合成的一个无序集合,能够经过键俩访问值。值通常由,基本数据类型 和 object 组合。javascript
有三种方式:java
使用new来建立一个对象
var person = new Object();
甚至能够简写成为: var person = new Object;
json
var o = { a : 1}; var p = new Object(o); alert(o === p); // true
var o1 = new Object("123"); console.log(o1); // String{0:"1",1:"2",2:"3",length:3,__proto__: String, [[PrimitiveValue]]: "123"} var o2 = new Object(123); console.log(o2) // Number{123, __proto__: Number, [[PrimitiveValue]]: 123} var o3 = new Object(true); console.log(o3) // Boolean {__proto__: Boolean, [[PrimitiveValue]]: true} // ------------ 下面是空对象 和不传参数同样。 var o4 = new Object(null) console.log(o4) // Object{__proto__: Object} var o5 = new Object(undefined) console.log(o5) // Object{__proto__: Object} var o6 = new Object() console.log(o6) // Object{__proto__: Object}
这是咱们 最熟悉的一种,也是常用的一种,其实使用字面量只是隐藏了与使用new操做符相同的基本过程,因而也能够叫作语法糖。
简单示例:数组
var person = { age : 24, name: 'xiaoming', 1: true, }
注意,使用对象字面量方法来定义对象的时候,属性名会自动转化为字符串。
就是上面示例,自动变成下面的。函数
var person = { 'age' : 24, 'name': 'xiaoming', '1': true, }
ES5定义了一个名为Object.create()的方法,它建立一个新对象,第一个参数就是这个对象的原型,第二个可选参数用以对对象的属性进行进一步描述this
var o = Object({a:1}) console.log(o) // Object{a:1,__proto__:object}
注意:传入参数null来建立一个没有原型的新对象prototype
var o1 = Object.create(null); var o2 = {};
此时o1不会继承任何东西,甚至不包括基础方法。好比toString()和valueOf()。
若是想要建立一个普通的空对象(例如,经过{}或new Object()建立的对象),须要传入Object.prototype, 这就是由于,这个函数的第一个参数就是原型对象。code
var o3 = Object.create(Object.prototype); var o4 = {};
若是不一样的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址。修改其中一个变量,会影响到其余全部变量。对象
var o = { a:1, } var p = o; console.log(p.a) // 1 p.a = 0; console.log(o.a) // 0
对象的属相操做,有两种 [] 和 点号(.)。
点号(.), 在使用的时候,属性名必须符合标识符的命名规则。
不存在的属性取值返回undefined。继承
var o = { a : 0, 1 : true, } o.b = 1; // 能够增长属性,并赋值 console.log(o.a) // 能够取值操做 console.log(o.1) // 报错 console.log(o.b) // undefined 不存在的变量 o.a = 2; // 能够赋值操做 console.log(o.a);
[] 方括号中的值, 如果字符串,则直接访问。 若是非字符串类型且不符合标识符命名,则转成字符串访问,若是非字符串类型且符合标识符命名,则须要识别变量的值,变量未定义,则报错。
在[] 访问属性的时候 是能够计算属性的
var c = 1; var o = {} console.log(o[0]) // undefined o[0] --> o['0'] 访问。 console.log(o[a]) // 报错,a符合变量的命名规则,a未被定义,而报错 console.log(o['a']) // undefined o['a'] 访问。 console.log(o[null]) // undefined , o[null] --> o['null']访问 console.log(o[c + 1]) // undefined o[c+1] --> o['4']访问
注意 null和undefined不是对象,给它们设置属性会报错
使用delete运算符能够删除对象属性(包括数组元素)。
delete是有返回值的,删除成功则返回true,删除不存在的属性或非左值时,返回false。当使用delete操做符删除不可配置的属性时,返回false,严格模式下会抛出TypeError错误
将属性赋值为 null 和undefined 只是修改了属性的值。
var o = { a:1 } console.log(delete o.a);//true console.log(o.a);//undefined console.log('a' in o);//false in 操做符 能够判断对象是否具备该属性,可是没法判断是不是继承来的
使用delete删除数组元素时,不会改变数组长度
var a = [1,2,3]; delete a[2]; 2 in a;//false a.length;//3
每个javascript对象都和另外一个对象相关联。“另外一个对象”就是咱们熟知的原型对象,每个对象都会从原型对象继承属性。
对象自己具备的属性叫自有属性,从原型对象继承而来的属性叫继承属性
in: in操做符能够判断对象是否可使用某一属性,但没法区别自有仍是继承属性
for-in: for-in循环能够遍历出该对象中全部可枚举属性
hasOwnProperty(): 能够肯定该属性是自有属性仍是继承属性
Object.keys(): 返回全部可枚举的自有属性
Object.getOwnPropertyNames(): Object.keys()方法不一样,Object.getOwnPropertyNames()方法返回全部自有属性(包括不可枚举的属性)
对象属性描述符分为, 数据属性 访问器属性
数据属性(data property)包含一个数据值的位置,在这个位置能够读取和写入值。
var o = {a:1}; Object.defineProperty(o,'a',{ configurable:false, }); delete o.a; //false 严格模式下报错 console.log(o.a);//1
var o = {a:1}; Object.defineProperty(o,'a',{ configurable:false }); // 报错不能修改属性 Object.defineProperty(o,'a',{ configurable:true });
可枚举enumerable
可枚举性决定属性是否出如今对象的属性枚举中,具体来讲,for-in循环、Object.keys方法、JSON.stringify方法是否会取到该属性。
var o = {a:1}; Object.defineProperty(o,'a',{enumerable:false}); for(var i in o){ console.log(o[i]);//undefined }
var o = {a:1}; Object.defineProperty(o,'a',{ writable:false }); console.log(o.a);//1 o.a = 2;//因为设置writable为false,因此o.a=2这个语句会默认失效,严格模式会报错 console.log(o.a);//1
属性值value
属性值包含这个属性的数据值,读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。默认值为undefined
访问器属性不包含数据值;它们包含一对儿getter和setter函数(不过,这两个函数都不是必需的)。在读取访问器属性时,会调用 getter函数,这个函数负责返回有效的值;在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。
get是一个隐藏函数,在获取属性值时调用。set也是一个隐藏函数,在设置属性值时调用,它们的默认值都是undefined。Object.definedProperty()中的get和set对应于对象字面量中get和set方法
[注意]getter和setter取代了数据属性中的value和writable属性
一般这里的get和set是用来 拦截数据访问和修改的。
var o = { get a(){ return 0; } } console.log(o.a) // 0 o.a = 1 // 没有set方法, 默认失效 console.log(o.a) // 0 // --------------------------------------- Object.defineProperty(o,'b',{ get: function(){ return 2; } }) console.log(o.b);//2 //因为没有设置set方法,因此o.a=3的赋值语句会静默失败 o.b = 1; console.log(o.b);//2
只有set
var o = {} Object.defineProperty(o,'a',{ set: function(){ return 0; } }) o.a = 1; console.log(o.a);//undefined
一般状况下 get 和set是成对出现的, 而且你会发现,这样作,咱们还须要空间来存储值。 这也是数据属性的不一样之处吧。
var o = {}; Object.defineProperty(o,'a',{ get: function(){ return this._a; }, set :function(val){ this._a = val*2; } }) o.a = 1; console.log(o.a);//2
var o = {a : 0}; // Object {value: 0, writable: true, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(o,'a')); // undefined console.log(Object.getOwnPropertyDescriptor(o,'b'));
var o = {}; Object.defineProperty(o,'a',{ value: 0, writable: true, enumerable: true, }); // /{value: 1, writable: true, enumerable: true, configurable: false} 没有配置因为没有配置configurable,因此它的值为false console.log(Object.getOwnPropertyDescriptor(o,'a'))
var o = { a : 1, } Object.defineProperties(o,{ a:{enumerable:false}, b:{value:2} }) //{value: 1, writable: true, enumerable: false, configurable: true} console.log(Object.getOwnPropertyDescriptor(o,'a')); //{value: 2, writable: false, enumerable: false, configurable: false} console.log(Object.getOwnPropertyDescriptor(o,'b'));
var o = Object.create(Object.property,{ a:{ value: 0, writable: false, enumerable: true, }, b{ value: 1, } }) //{value: 0, writable: false, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(obj,'a')); // {value: 1, writable: true, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(obj,'b'))
使用for-in将对象的全部属性复制到新建的空对象中,并将器返回
function simpleClone(o,cloneObj){ // 判断参数 for(var i in obj){ cloneObj[i] = obj[i]; } return cloneObj; }
使用属性描述符
function simpleClone(o){ // 判断参数 var cloneObj = Object.create(Object.getPrototypeOf(o)); // 根据o对象的原型对象,建立新对象。 // 获取自身属性并迭代。 Object.getOwnPropertyNames(o).forEach(function(propKey){ // 根据自身属性名 获取属相描述。 var desc = Object.getOwnPropertyDescriptor(o,propKey); // 给克隆对象设置 属性描述 Object.defineProperty(cloneObj,propKey,desc); }); return cloneObj; }
复制对象的属性时,对其进行判断,若是是数组或对象,则再次调用拷贝函数;不然,直接复制对象属性
function deepClone(o,cloneObj){ if(typeof o != 'object'){ return false; } var cloneObj = cloneObj || {}; // 保证cloneObj不是null和undefined for(var i in o){ if(typeof o[i] === 'object'){ // 是对象继续递归拷贝 cloneObj[i] = (o[i] instanceof Array) ? [] : {}; arguments.callee(o[i],cloneObj[i]); }else{ cloneObj[i] = o[i]; } } }
使用 json.
先是对象转成字符串,而后在转成对象返回。
function jsonDeepClone(o){ return JSON.parse(JSON.string(o)) }