2013-04-27 53 views
0

我想了解JavaScript對象,但我很難與不同類型的聲明。瞭解JavaScript對象(不同類型的聲明)

作爲I read有定義一個對象

方法1的兩個主要途徑:

var student1 = { 
    name: "Peter Foti", 
    course: 'JavaScript', 
    grade: 'A', 
    dispInfo: function(){ 
     return this.name + ' has an ' + this.grade; 
    } 
}; 

方法2:

function student (a, b, c) { 
    this.name = a; 
    this.course= b; 
    this.grade = c; 
    this.dispInfo = function(){ 
     return this.name + ' has an ' + this.grade; 
    } 
} 

對於方法2 I理解概念,如果我想創建一個類型爲student的變量,我只需要c所有:

student1 = new student("Jean Dupont", "wine tasting", "A"); 
console.log(student1.dispInfo); 

然而,與方法1,我怎麼能不創建再次寫入所有內部功能,如dispInfo一個STUDENT2?

我願做這樣

var student2 = { 
    name: "Olivier Perraut", 
    course: 'Pétanque', 
    grade: 'F' 
}; 

console.log(student2.getInfo); 

回答

2

第一種方法是創建你永遠只能打算有一個的對象。這是單身人士。它直接創建student1對象。

第二種方法是構造函數。可以一次又一次地使用構造函數來創建儘可能多的這些對象。

按照慣例,構造函數首先應該覆蓋的(例如,Student而非student),比如JavaScript自己的對象(DateRegExp,...)。

你可以使用JavaScript原型鏈,使所有的Student對象使用相同的dispInfo功能(具有不同this值),而不是爲每個對象創建dispInfo

function Student (a, b, c) { 
    this.name = a; 
    this.course = b; 
    this.grade = c; 
} 
Student.prototype.dispInfo = function(){ 
    return this.name + ' has an ' + this.grade; 
}; 

var s1 = new Student("Mary", "Algebra", "A"); 
var s2 = new Student("Joe", "Classical Sculpture", "B+"); 

由於ES5的(和對於較老的瀏覽器,這也可以用「墊片」來實現),您不必使用構造函數來使對象共享一個原型,您可以使用Object.create來做到這一點。我更喜歡構造函數,但你也可以使用建設者功能:

var StudentPrototype = { 
    dispInfo: function(){ 
     return this.name + ' has an ' + this.grade; 
    } 
}; 
function BuildStudent(a, b, c) { 
    var student = Object.create(StudentPrototype); 
    student.name = a; 
    student.course = b; 
    student.grade = c; 
    return student; 
} 
var s1 = BuildStudent("Mary", "Algebra", "A"); 
var s2 = BuildStudent("Joe", "Classical Sculpture", "B+"); 

請注意,我們使用new與建設者的功能,只需用構造函數。 (如果你這樣做通常是無害的,但是讀取代碼的人沒有必要和誤導,所以你不想。)

或者你甚至不需要在簡單的情況下,設計器功能,您可以只使用Object.create直接,但它是一個有點麻煩,因爲如果你在屬性描述(第二個參數)傳球,每一個成爲一個描述財產的物體,而不僅僅是它的價值(這有一個很好的理由),所以你必須做{value: "the value"}(當然,你可能需要來指定有關財產的其他事情,比如它是否是enumerable等):

var StudentPrototype = { 
    dispInfo: function(){ 
     return this.name + ' has an ' + this.grade; 
    } 
}; 
var s1 = Object.create(StudentPrototype, { 
     name: {value: "Mary"}, 
     course: {value: "Algebra"}, 
     grade: {value: "A"} 
}); 
var s2 = Object.create(StudentPrototype, { 
     name: {value: "Joe"}, 
     course: {value: "Classical Sculpture"}, 
     grade: {value: "B+"} 
}); 

就個人而言,我更喜歡構造函數functio ns,但關於JavaScript的好處在於它支持多種編程風格,其中包括諸如構建器或直接使用Object.create等更合適的編程風格。

+0

Thx爲答案。事情是,我不會總是想要用所有參數來初始化對象。這就是爲什麼一種陣列會很好。 我知道我總是可以使用s.name =「Mary」 – 2013-04-27 09:34:58

+0

@PaulFournel:你可以放棄那些你想離開的東西(如果它們在最後);在構造函數中,它們將是'undefined'。例如,'var s = new Student(「Mary」);'產生一個名字爲'course'和'grade'的值爲undefined的學生。你也可以將一個「選項」對象傳遞給構造函數,該構造函數從該對象的屬性中抓取它需要的東西(jQuery - 你可能已經聽說過了 - 用它作爲'$ .ajax'等等,就像其他圖書館)。 – 2013-04-27 09:40:45

+0

@PaulFournel:或者,當然,對於你正在做的事情,你可以直接使用Object.create(參見答案的結尾)。我不是直接使用它的大粉絲,但有很多人。 :-) – 2013-04-27 09:41:28

0

東西試試這個。儘管我寧願用方法2來實現這一點。

var student1 = { 
    name: "Peter Foti", 
    course: 'JavaScript', 
    grade: 'A', 
    dispInfo: function(){ 
     return this.name + ' has an ' + this.grade; 
    } 
}; 

function GenerateObject (objValues) 
{ 
    var object = Object.create(student1); 
    for(var i in objValues) 
    { 
     object[i] = objValues[i] 
    } 
    return object; 
} 
var student2 = GenerateObject({ 
    name: "Olivier Perraut", 
    course: 'Pétanque', 
    grade: 'F' 
    }); 
+0

是方法2似乎更好的解決方案就是這種情況。 Thx爲您的快速回答:) – 2013-04-27 09:37:29

2

JavaScript是一種所謂的基於原型的面嚮對象語言。這意味着對象不會獲得由類,特徵,混合等定義的行爲,而是直接從其他對象繼承它。

所以,如果你想有一個student2的行爲像student1只有一些細微的差異,那麼你只是從student1繼承和覆蓋那些不同的屬性。在JavaScript中,使用Object.create函數設置原型繼承,該函數接受要繼承的對象以及具有重寫屬性的可選屬性描述符映射。

var student1 = { 
    name: "Peter Foti", 
    course: 'JavaScript', 
    grade: 'A', 
    dispInfo: function() { return this.name + ' has an ' + this.grade; } 
}, 

    student2 = Object.create(student1, { 
    name: { value: 'Olivier Perraut' }, 
    course: { value: 'Pétanque' }, 
    grade: { value: 'F' } 
}); 

console.log(student2.dispInfo()); 
// Olivier Perraut has an F 

很多時候,你會看到一個模式不斷涌現,其中的而不是「企業」對象相互直接繼承,你將建立一個原始的「模板」對象,有你的所有業務對象從繼承,有點像這樣:

var studentTemplate = { 
    dispInfo: function() { return this.name + ' has an ' + this.grade; } 
}, 

    student1 = Object.create(studentTemplate, { 
    name: { value: 'Peter Foti' }, 
    course: { value: 'JavaScript' }, 
    grade: { value: 'A' } 
}), 

    student2 = Object.create(studentTemplate, { 
    name: { value: 'Olivier Perraut' }, 
    course: { value: 'Pétanque' }, 
    grade: { value: 'F' } 
}); 

console.log(student1.dispInfo()); 
// PeterFoti has an A 

console.log(student2.dispInfo()); 
// Olivier Perraut has an F 

順便說一句,我認爲這將是一個好主意,以dispInfo一個getter屬性,而不是一個方法:

var studentTemplate = {}; 

Object.defineProperty(studentTemplate, 'info', { 
    get: function() { return this.name + ' has an ' + this.grade; } 
}); 

var student1 = Object.create(studentTemplate, { 
    name: { value: 'Peter Foti' }, 
    course: { value: 'JavaScript' }, 
    grade: { value: 'A' } 
}); 

console.log(student1.info); 
// PeterFoti has an A 
+0

Thx爲您的答案。有沒有一種方法來定義對象,而不必使用'name:{value:'Olivier Perraut'}'而只是'name:'Olivier Perraut'' – 2013-04-27 09:54:03

+1

@PaulFournel:不在'Object.create'調用中雖然可以在'Object.create'之後分配'student1.name ='Joe'')。這是因爲描述符必須是一個對象,它不能只是一個值(因爲否則就會產生歧義 - 如果使用了一個對象,是指該對象是屬性的值還是描述符?)。這是爲什麼我更喜歡構造函數或構建函數的一部分,而不是直接使用'Object.create'。直接使用它可能有點冗長。 – 2013-04-27 10:02:26