简体   繁体   English

了解javascript对象(声明的不同类型)

[英]Understanding javascript object (different type of declaration)

I am trying to understand the javascript objects, but I am having a hard time with the different types of declarations. 我试图了解javascript对象,但是使用不同类型的声明很难。

As I read there are two main way to define an object 我阅读时 ,定义对象的主要方法有两种

Method 1: 方法1:

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

Method 2: 方法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; 
    }
}

For the method 2 I understand the concept, if I want to create a variable of type student I simply need to call : 对于方法2,我理解这个概念,如果我想创建一个Student类型的变量,我只需要调用:

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

However, with the method 1, how can I create a student2 without writing again all the inner function such as dispInfo? 但是,使用方法1,如何在不再次编写所有内部函数(例如dispInfo)的情况下创建student2?

I would like to do something like 我想做类似的事情

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

console.log(student2.getInfo);

The first method is for creating an object that you only ever intend to have one of. 第一种方法是创建您只打算拥有一个的对象。 It's for singletons. 用于单身人士。 It creates the student1 object directly. 它直接创建student1对象。

The second method is a constructor function . 第二种方法是构造函数 Constructor functions can be used again and again to create as many of these objects as you need. 构造函数可以一次又一次地用于创建所需数量的这些对象。

By convention, constructor functions should be initially-capped (eg, Student rather than student ), like JavaScript's own objects ( Date , RegExp , ...). 按照惯例,构造函数应该是最初覆盖的(如Student ,而不是student ),比如JavaScript自己的对象( DateRegExp ,...)。

You could use the JavaScript prototype chain so that all of the Student objects use the same dispInfo function (with different this values) rather than creating a dispInfo for every object: 您可以使用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+");

As of ES5 (and this is possible with "shims" as well, for older browsers), you don't have to use a constructor function to have objects that share a prototype, you can use Object.create to do that. 从ES5开始(对于较旧的浏览器,“垫片”也可以实现),您不必使用构造函数来拥有共享原型的对象,您可以使用Object.create来实现。 I prefer constructor functions, but you can also use builder functions: 我更喜欢构造函数,但你也可以使用生成器功能:

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+");

Note that we don't use new with builder functions, just with constructor functions. 请注意,我们不会new与构建函数一起使用,而仅将其与构造函数一起使用。 (It's usually harmless if you did, but it's unnecessary and misleading to anyone reading the code, so you don't want to.) (如果这样做,通常通常是无害的,但这是不必要的,并且会误导任何阅读该代码的人,因此您不想这样做。)

Or you don't even need the builder function in that simple case, you can just use Object.create directly, but it's a bit cumbersome because if you pass in property descriptors (the second argument), each one has to be an object describing the property, not just a value for it (there's a good reason for that), so you have to do {value: "the value"} (of course, you might want to specify other things about the property, like whether it's enumerable , etc.): 或者在这种简单情况下甚至不需要构建器功能,您可以直接使用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+"}
});

Personally, I prefer constructor functions, but the great thing about JavaScript is that it supports multiple styles of programming, including ones where things like builders or using Object.create directly are more appropriate. 就个人而言,我更喜欢构造函数,但是JavaScript的妙处在于它支持多种编程样式,包括那些更适合使用builders或直接使用Object.create类的样式。

JavaScript is a so-called prototype-based object-oriented language. JavaScript是一种所谓的基于原型的面向对象语言。 This means that objects don't get their behavior defined by classes, traits, mixins etc., but instead inherit it directly from other objects. 这意味着对象不会通过类,特征,mixins等来定义其行为,而是直接从其他对象继承它。

So, if you want to have a student2 that behaves like a student1 with only some minor differences, then you simply inherit from student1 and override those properties that are different. 所以,如果你想有一个student2其行为类似student1 ,只有一些细微的差别,那么你只需继承student1并覆盖那些不同的性质。 In JavaScript, prototypal inheritance is set up using the Object.create function, which takes in the object to inherit from and an optional property descriptor map with the overridden properties. 在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

Often times, you will see a pattern emerging, where instead of having "business" objects inherit directly from each other, you will set up a pristine "template" object and have all your business objects inherit from that, kind of like this: 通常,您会看到一种模式在出现,在该模式中,您将设置一个原始的“模板”对象,并使所有业务对象都从该类继承,而不是让“业务”对象直接从彼此继承,就像这样:

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

By the way, I think it would be a good idea to make dispInfo a getter property instead of a method: 顺便说一句,我认为将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

Try this. 尝试这个。 Though I would prefer to go with the method 2 to achieve this. 尽管我更愿意使用方法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'
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM