建立对象有两种方法:1,声明形式;2,构造形式。javascript
//声明形式
let obj = {
a:2,
...
}
//构造形式
let obj = new Object();
obj.a = 2;
...
复制代码
js中有6中数据类型:string,number,boolean,null,undefined,object
,简单数据类型string,number,boolean,null,undefined
自己并非对象,可是null
有时会被当作对象,但这是js语言的一个bug,即在执行typeof null
时会返回object
,实际上null是基本数据类型。其原理是,不一样的对象在底层都是用二进制来表示的,在javascript中二进制前三位为0就表示是对象,null
的二进制表示是全0
,即前三位都是0
,因此执行typrof null
时返回object
。java
js中有一些对象子类型,称为内置对象:String,Number,Boolean,Object,Function,Array,Date,RegExp,Error
。在必要时语言会把基本数据类型隐式的转换成其对应的构造形式。 null 和 undefined
没有对应的构造形式,只有文字形式,Date
没有文字形式,只有构造形式。es6
访问对象的属性能够有两种方式:1,.a
语法一般叫作“属性访问”;2,['a']语法一般叫作“键访问”。主要区别在于.
操做符须要属性名知足标识符的命名规范,[..]
操做符能够接受任意的字符串。 在ES6中新增长了计算属性,能够在声明形式中使用[]
包裹一个表达式表示一个属性名:数组
let pre = 'pre';
let obj = {
[per + 'foo']:'foo',
[per + 'baz']: 'baz'
}
obj['prefoo'];//'foo'
obj['prebaz'];//'baz'
复制代码
你能够向数组中添加属性,添加的属性不会修改数组的长度,而且能够正常的访问它。bash
let arr = [2,3,4];
arr.foo = 'foo';
arr.length;// 3
arr.foo;// 'foo'
复制代码
可是若是你向数组添加一个“看起来”像数字的属性,那它会变成一个数值下标,从而改变数值而不是成为数值的属性。ui
let arr = [2,3,4];
arr['3'] = 'foo';
arr.length;// 4
arr[3];// 'foo'
复制代码
js语言自己并无提供内置的深拷贝方法,可是有一种巧妙的运用JSON的方法能够实现对象的深拷贝:this
let newObj = JSON.parse(JSON.stringify(obj))
复制代码
ES6提供了对象的浅拷贝方法:Object,assign()
,Object.assign()
方法第一个参数为目标对象,后面跟一个或多个源对象,遍历源对象中因此可枚举的属性添加到目标对象,而且返回目标对象。Object.assign()
使用的是=
操做符来复制,因此并不会复制属性的一些特性(好比writable)。spa
对象的每个属性有三个特性:writable(决定是否能够修改属性的值),enumerable(是否可枚举),configurable(是否可配置)
,当咱们建立一个属性时都会使用特性的默认值,即都为true
,咱们可使用Object.defineProperty()
来新建一个属性或者修改一个已存在属性的特性。prototype
let obj = {};
Object.defineProperty(obj,'a',{
value:'foo',
writable:true,
enumerable:true,
configurable:true,
});
obj.a;// 'foo'
复制代码
当configurable
设置为false
时,除了没法修改,还会禁止删除该属性。code
1,建立一个常量属性: 将一个对象的writable
和configurable
都设置为false
,就能够建立一个真正的常量属性,不可修改,不可设置,不可删除。
2,禁止扩展: 若是要禁止一个对象添加新的属性而且保留已有的属性,可使用Object.preventExtensions()
,
lat obj = {
a:'foo',
}
Object.preventExtensions(obj);
obj.b = 'baz';
obj.b;// undefined
复制代码
在非严格模式下建立属性b
默认失败,在严格模式下会抛出TypeError
错误。
3,密封:Object.seal()
会建立一个密封的对象,该方法其实是在一个对象上调用Object.preventExtensions()
方法,而且把因此属性标记为configurable:false
,使得对象不能添加新属性,不能配置,不能删除任何属性。
4,冻结:object.freeze()
会建立一个冻结对象,该方法实际是在对象上调用Object.seal()
,并把属性标记为writable:false
,使得对象不可新增属性,不可删除属性,属性不可配置,属性不可修改。
当咱们访问对象的属性时,其实是在调用对象默认的Get
方法,Get
如今对象的属性上查找是否有该属性,若是有就返回;若是没有就遍历其可能存在的[prototype]
链;若是不管如何都找不到就返回undefined
。
当给对象赋值时会触发Put
,若是这个属性已经存在啦:1,首先判断属性是不是访问描述符(定义了getter,setter
或者二者都有),若是存在setter
就调用setter
;2,属性的数据描述符中writable
是否为false
,是的话严格模式下抛出TypeError
错误,非严格模式下静默失败。3,若是都不是将该值设为属性的值。
注:当给一个属性设置getter、setter
或者二者都有时,这个属性会被定义为‘访问描述符‘’,和‘数据描述符’相对。对于访问描述符,js会忽略它的value
和writable
特性,会关心它的set和get
还有configurable和enumerable
。
检查对象中是否存在一个属性可使用in
操做符,或者使用hasOwnProperty()
方法。in
操做符会检查对象的属性和它的[prototype]
链;hasOwnProperty()
只会检测对象的属性列表。
Object.keys()
会返回包含全部可枚举的属性的数组;Object.getOwnPropertyNames()
返回包含全部属性的数组,不管是否可枚举。
es6新增了for..of
循环,for...of
循环首先会向被访问的对象请求一个迭代器对象,而后经过调用迭代器对象的next()
方法来遍历因此返回值。数组有内置的@@iterator
,所以for...of
循环能够直接做用在数组上。
let arr = [1,2,3];
for(let v of arr){
console.log(v);
}
//1,2,3
复制代码
若是想用for...of
遍历对象的属性值,咱们须要在对象上定义@@iterator
:
let obj = {
a:2,
b:3,
}
Object.defineProperty(obj,Symbol.iterator,{
enumerable:false,
writable:false,
configurable:true,
value:function(){
let o = this;
let keys = 0;
let k = Object.keys(o);
return {
next:function(){
return {
value:o[k[keys++]],
done:keys > k.length
}
}
}
}
})
//手动遍历
let it = obj[Symbol.iterator]();
it.next();//{value:2,done:false}
it.next();//{value:3,done:false}
it.next();//{value:undefined,done:true}
//使用for...of遍历
for(let v of obj){
console.log(v);
}
//2 3
复制代码