2014年10月17日 星期五

[Javascript] Best way to store key-value array (存 key-value 陣列的最佳方法) / Object v.s. Array tips (物件 v.s. 陣列 小撇步)


資料型態簡單釋義

物件 (Object)

可以存放屬性和函式的容器。

陣列 (Array)

可以存放多個不一定要相同資料型態變數的容器。

當兩種型態皆可使用時,如何選擇?

以學生 (Student) 舉例,學生的屬性有姓名 (Name)、性別 (Gender)、座位 (Seat Number)。
現在有三位學生,Mary、Tom、Mark。

陣列搭配物件 (Objects in Array) 寫法

var studentArray = [{
    name: "Mary",
    gender: "Female",
    seatNumber: 1
}, {
    name: "Tom",
    gender: "Male",
    seatNumber: 2
}, {
    name: "Mark",
    gender: "Male",
    seatNumber: 3
}];

純物件 (Objects in Object) 寫法

var studentsObjectA = {
    Mary: {
        gender: "Female",
        seatNumber: 1
    },
    Tom: {
        gender: "Male",
        seatNumber: 2
    },
    Mark: {
        gender: "Male",
        seatNumber: 3
    }
}
或者
var studentsObjectB = {
    1: {
        name: "Mary",
        gender: "Female"
    },
    2: {
        name: "Tom",
        gender: "Male"
    },
    3: {
        name: "Mark",
        gender: "Male"
    }
}

情況一

若只有要取某一個物件,或者做搜尋,像是
取其中某一個名字的學生、某一個座位的學生資料、
確認某個座位有沒有人、某一個名字有沒有人用、
增刪學生、增刪學生資料,
使用純物件 (Objects in Object) 會比陣列搭配物件 (Objects in Array) 方便。

陣列搭配物件 (Objects in Array) 寫法

var EMPTY = null;
var FAIL = false;
var SUCCESS = true;

function getStudentByName(name) {
    for(student in studentArray) {
        if(student.name == name) {
            return student;
        }
    }
    return EMPTY;
}

function addStudent(name, gender, seatNo) {
    studentArray.push({
        name: name,
        gender: gender,
        seatNumber: seatNo
    });
    return studentArray;
}

function removeStudentByName(name) {
    var i;
    for(i = 0; i < studentArray.length; i++) {
        if(student.name == name) {
            break;
        }
    }
    if(i == studentArray.length) {
        return SUCCESS;
    }
    studentArray.splice(i, 1);
    return SUCCESS;
}

純物件 (Objects in Object) 寫法

var EMPTY = null;
var FAIL = false;
var SUCCESS = true;

function getStudentByName(name) {
    if(studentsObjectA[name] != undefined) {
        studentsObjectA[name].name = name;
        return studentsObjectA[name];
    }
    return EMPTY;
}

function getStudentBySeatNumber(number) {
    if(studentsObjectB[number] != undefined) {
        studentsObjectB[number].seatNumber = number;
        return studentsObjectB[number];
    }
    return EMPTY;
}

function addStudent(name, gender, seatNo) {
    studentsObjectA[name] = {
        gender: gender,
        seatNumber: seatNo
    };
    return studentsObjectA;

    // studentsObjectB["" + seatNo] = {
    //     name: name,
    //     gender: gender
    // };
    // return studentsObjectB; 
}

function removeStudentByName(name) {
    delete studentsObjectA[name]
    return SUCCESS;
}

其實就是變相加索引值 (indexing),或者說,把索引值的可使用性提升,
從純粹順序 index,到有意義的 index。

在這種情況下,純物件 (Objects in Object) 用起來方便多了,時間複雜度也較小,
缺點是如果拿去當屬性名稱/索引值的屬性是重要的、要一起取的,
要再加回去,或者一開始就多加一次。

情況二

若有需要每一個物件都要處理某件事情,像是所有學生換座位,
無論使用哪一種,使用方式和時間複雜度都差不多。

陣列搭配物件 (Objects in Array) 寫法

var SUCCESS = true;

function changeSeat() {
    for(student in studentArray) {
        student.seatNum++;
        if(student.seatNum == 4) {
            student.seatNum = 1;
        }
    }
    return SUCCESS;
}

純物件 (Objects in Object) 寫法

var SUCCESS = true;

function changeSeat() {
    for(var name in studentsObjectA) {
        var student = studentsObjectA[name];
        student.seatNum++;
        if(student.seatNum == 4) {
            student.seatNum = 1;
        }
    }
    return SUCCESS;
}

結論

純物件 (Objects in Object) 的用法顯然比陣列搭配物件 (Objects in Array) 的用法方便也快多了,就易用性來說,純物件 (Objects in Object) 勝!但,宣告為陣列讓人一看就知道是很多個同樣物件,而宣告為物件則還要看做些什麼事情才能知道內容物的長相,所以就易讀性上來說,陣列搭配物件 (Objects in Array) 勝!

實際使用,還是依據大家的需要和架構設計來決定囉!



沒有留言:

張貼留言