建立對象有兩種方法: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
複製代碼