如何在新的ECMAScript 2015 JavaScript类中定义getter和setter

时间:2017-01-29 17:01:49

标签: javascript

我正在尝试使用定义为here的新ECMAScript 2015 JavaScript类来定义一个名为Mail的简单类。

我想出了这个构造函数并尝试了以下getter:

class Mail {
   constructor(sender, date, subject, text) {
        this.sender = sender;
        this.date = date;
        this.subject = subject;
        this.text = text;
   }
   get sender() {
       return this.sender;
   }
}

但是当我尝试使用该方法时,它无效。

var mail = new Mail("@mail.com", Date.now(), "Testing", "Text");
console.log(mail.sender());

返回:

TypeError: mail.sender is not a function

所以,我怀疑是:

  1. 是否有必要像Java一样定义getter和setter,或者我可以简单地访问mail.sender之类的字段(或左右)?
  2. 如果有必要,如何正确定义每个类实例变量的getter和setter?

4 个答案:

答案 0 :(得分:3)

getter和setter基本上是用于捕获对象的属性的get-和set-动作的钩子。它们是函数,但它们似乎是(对于使用此Object的代码),就像属性一样。

var mail = new Mail("@mail.com", Date.now(), "Testing", "Text");
console.log(mail.sender); //no brackets

如果你添加了一个setter,main.sender = "@foo.bar"

我想知道你的代码没有陷入无限递归,因为你的getter自称。

class Mail {
   constructor(sender, date, subject, text) {
        this._sender = sender;
        this._date = date;
        this._subject = subject;
        this._text = text;
   }

   //this IS `this.sender`!
   //it should not `return this.sender`, since this would call this getter again, 
   //and you get stuck in an infinite recursion.
   get sender() {
       return this._sender;
   }

   //and a possible setter, that handles 
   //instance.sender = whatever;
   set sender(value) {
       this._sender = value;
   }
}

修改

  

这是否意味着我可以忽略get和set方法,因为我可以直接访问对象字段?

您不需要getter或setter来在JS中公开任何属性,只需定义此属性即可使其公开可用。 JS以相反的方式工作,你必须付出额外的努力来使事情变得私密(见封闭)。在JS中,默认情况下一切都是公开的。

但您可以使用getter(和setter)来完成其他任务,例如:

class Person{
    constructor(firstName, lastName){
        //regular public properties
        this.firstName = firstName;
        this.lastName = lastName;
    }

    //a composed value, that you can access like a property
    get fullName(){
        return this.firstName + " " + this.lastName;
    }

    //you could also add a setter like this
    set fullName(value){
        [this.firstName, this.lastName] = value.split(/\s+/g);
    }
}

var john = new Person("John", "Doe");
console.log(john.fullName);

答案 1 :(得分:0)

你实际上做的比你需要的多。你不需要按照你的指定使用吸气剂。

试试这个:

class Mail {
 constructor(sender, date, subject, text) {
    this.sender = sender;
    this.date = date;
    this.subject = subject;
    this.text = text;
  }
}

var mail = new Mail("@mail.com", Date.now(), "Testing", "Text");
console.log(mail.sender);

答案 2 :(得分:0)

要使用getter和setter,您只需使用并设置属性即可。在你的情况下:mail.sender。如果您正在使用该值,则会调用getter;如果您覆盖当前值,则调用setter。



class Mail {
    constructor(sender) {
        this._sender = sender;
    }

    get sender() {
        return "Sender: " + this._sender;
    }

    set sender(val) {
        this._sender = val.toLowerCase();
    }
}

const m = new Mail("TEST");
console.log(m.sender); // => "Sender: TEST"

m.sender = "TEST";
console.log(m.sender); // => "Sender: test"




请注意,我使用_sender存储了值以阻止Maximum call stack size exceeded error

您可以像使用任何其他属性一样使用该属性,它会自动调用getter或setter。

如果你要找的是封装,你可以像这样设计你的类:

const Mail = (function() {
    let sender; // this is "private"

    return {
        title: "public", // This is public
        get sender() {
            return sender;
        },
        // ...
    };
});

在这种情况下,您将创建新的Mail对象,如下所示:

const mail = Mail();

您可以在Mail函数中返回一个函数,以便能够使用new关键字实例化新对象。

答案 3 :(得分:0)

JavaScript没有类的概念。 class关键字只是语法糖。

class做什么,它为您生成constructor function

const Person = class { // or `class Person`
    constructor(name) {
        this.name = name;
    }

    say(msg) {
        return `${this.name} says: "${msg}".`;
    }
}

完全相同,您将通过以下代码实现。

const Person = function(name) {
    this.name = name;
};

Person.prototype = {
    say(msg) {
        return `${this.name} says: "${msg}".`;
    }
};

如果您需要私有变量,则必须使用闭包。

const Person = class { // or `class Person`
    constructor(name) {
        this.getName = () => name;
        this.setName = (newName) => {
            name = newName;
        }
    }

    say(msg) {
        return `${this.getName()} says: "${msg}".`;
    }
}

let p = new Person('me');
console.log(p.name); // undefined
console.log(p.getName()); // 'me'
p.setName('he');
console.log(p.getName()); // 'he'
console.log(p.say('something')); // 'he says: "something".'

我建议您不要使用class并避免new。 如果您需要一个对象,只需使用factory functions

即可
const Person = function(name) {
    let person = Object.create(Person.prototype);
    person.name = name;
    return person;
};

Person.prototype = {
    say(msg) {
        return `${this.name} says: "${msg}".`;
    }
};