0

我试图理解 javascript 对象,但我很难处理不同类型的声明。

正如我所读到的,有两种主要的方法来定义一个对象

方法一:

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

方法二:

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,我理解这个概念,如果我想创建一个 student 类型的变量,我只需要调用:

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);
4

3 回答 3

2

第一种方法是创建一个您只打算拥有的对象。这是给单身人士的。它直接创建student1对象。

第二种方法是构造函数。可以一次又一次地使用构造函数来创建所需数量的这些对象。

按照惯例,构造函数最初应该是有上限的(例如,Student而不是student),就像 JavaScript 自己的对象(Date, RegExp, ...)一样。

您可以使用 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 开始(对于旧版浏览器,“shims”也可以),您不必使用构造函数来拥有共享原型的对象,您可以使用它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构建器函数,只使用构造器函数。(如果你这样做通常是无害的,但它对任何阅读代码的人来说都是不必要的和误导,所以你不想这样做。)

或者在那种简单的情况下你甚至不需要builder函数,你可以直接使用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+"}
});

就个人而言,我更喜欢构造函数,但 JavaScript 的优点在于它支持多种编程风格,包括那些Object.create更适合构建器或直接使用的编程风格。

于 2013-04-27T09:29:27.033 回答
2

JavaScript 是一种所谓的基于原型的面向对象语言。这意味着对象不会获得由类、特征、mixin 等定义的行为,而是直接从其他对象继承。

因此,如果您希望 astudent2的行为与 astudent1只有一些细微差别,那么您只需继承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
于 2013-04-27T09:36:53.583 回答
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'
    });
于 2013-04-27T09:28:01.570 回答