[JS]《你不知道的Javascript·上》——對象

對象的定義語法

聲明形式

var myObj={
    key:value,
    ...
}

構造形式

var myObj=new Object();
myObj.key=value;

JS的六種主要類型

  • string
  • number
  • boolean
  • null
  • undefined
  • object

內置對象(對象子類型)

  • String
  • Number
  • Boolean
  • Object
  • Function
  • Array
  • Date
  • RegExp
  • Error

內容

var myObj={
    a:2
};

myObj.a;//2——屬性訪問

myObj["a"];//2——鍵訪問

可計算屬性名

能夠在文字形式中使用[ ]包裹一個表達式來看成屬性名。數組

屬性與方法

從技術角度來講,函數永遠不會「屬於」一個對象,因此把對象內部引用的函數稱爲「方法」是不妥的。

數組

數組期待的是數值下標。最好只用對象來存儲鍵/值對,只用數組來存儲數值下標/值對。
若是試圖向數組添加一個屬性,可是屬性名「看起來」像一個數組,那麼它會變成一個數值下標(所以會修改數組的內容而不是添加一個屬性)。

複製對象——淺複製

var newObj=Object.assign( {},myObject );
Object.assign方法的第一個參數是目標對象,以後還能夠跟一個或多個源對象。它會遍歷一個或多個源對象的全部可枚舉的自有鍵,並把它們複製(使用=操做符賦值)到目標對象,最後返回目標對象。

屬性描述符

var myObj={
    a:2
 };

Object.getOwnPropertyDescriptor(myObj,"a");
/*{
    value:2,
    writable:true,
    enumerable:true,
    configurable:true
}*/

普通的對象屬性對應的屬性描述符除了key:value,還包含另外三個特性:writable(可寫)、enumerable(可枚舉)、configurable(可配置,將其修改成false是單向操做,沒法撤消)。函數

可使用Object.defineProperty(...)來添加一個新屬性或者修改一個已有屬性(若是它是configurable)並對特性進行設置。this

不變性

  1. 對象常量:結合writable:false和configurable:false就能夠建立一個真正的常量屬性。
  2. 禁止拓展:Object.preventExtensions(...)
  3. 密封:Object.seal(...)會建立一個密封的對象,其實是在一個現有對象上調用Object.preventExtensions(...)並把全部現有屬性標記爲configurable:false。因此密封以後不只不能添加新屬性,也不能從新配置或者刪除任何現有屬性(雖然能夠修改屬性的值)。
  4. 凍結:Object.freeze(...)會建立一個凍結對象,其實是在現有對象調用Object.seal(...)並設置爲writable:false,這樣就沒法修改它們的值。這是應用在對象上的級別最高的不可變性。

[[GET]]

對象默認的內置[[GET]]操做首先在對象中查找是否有名稱相同的屬性,若是找到就會返回這個屬性的值。若是不管如何都沒有找到名稱相同的屬性,那[[GET]]操做會返回值undefined。須要注意的是,這種方法和訪問變量時是不同的。若是你引用了一個當前詞法做用域中不存在的變量,並不會像對象屬性同樣返回undefined,而是會派出一個ReferenceError異常。code

[[PUT]]

Getter和Setter

一般來講getter和setter是成對出現的。對象

存在性

var myObj={
    a:2
};

("a" in myObj);//true
("b" in myObj);//false

myObj.hasOwnProperty("a");//true
myObj.hasOwnProperty("b");//false

in操做符會檢查屬性是否在對象及其[[Prototype]]原型鏈中。hasOwnProperty(...)只會檢查屬性是否在myObj中,不會檢查[[Prototype]]。ip

*:in實際上檢查的是某個屬性名是否存在。對於數組來講這個區別很是重要,4 in [2,4,6]的結果並非你的期待的true,由於[2,4,6]這個數組中包含的屬性名是0、一、2,沒有4。原型鏈

  • 枚舉
propertyIsEnumerable(...)//會檢查給定的屬性名是否直接存在於對象中
Object.keys(...)//會返回一個數組,包含全部可枚舉屬性
Object.getOwnpropertyNames(...)//會返回一個數組,包含全部屬性,不管是否可枚舉

遍歷

forEach(...)//會遍歷數組中的全部值並忽略回調函數的返回值
every(...)//會一直運行直到回調函數返回false
some(...)//會一直運行直到回調函數返回true

for...of

var myArray=[1,2,3];

for(var v of myArray){
    console.log(v);
}
//1
//2
//3

自定義迭代器

var myObj={
    a:2,
    b:3
};

Object.defineProperty(myObj,Symbol.iterator,{
    enumerable:false,
    writable:flse,
    configurable:true,
    value:function(){
        var o=this;
        var idx=0;
        var ks=Object.keys(o);
        return{
            next:function(){
                return{
                    value:o[ks[idx++]],
                    done:(idx>ks.length)
                };
            }
        };
    }
});



//手動遍歷myObj
var it=myObj[Sysbol.iterator]();
it.next();//{value :2,done:false}
it.next();//{value :3,done:false}
it.next();//{value :undefined,done:true}


//用for...of遍歷myObj
for (var v of myObj){
    console.log(v);
;

//2
//3
相關文章
相關標籤/搜索