在构造函数函数中创建只读(get)属性

Create read only (get) property in constructor function

本文关键字:get 属性 只读 创建 构造函数 函数      更新时间:2023-09-26

我正试图用Javascript在构造函数上创建一个只读属性。我重新混合了我在MDN上找到的语法,但这不起作用:

function Person(data) {
  var self = this;
  self.firstName = data.firstName || "John";
  self.lastName = data.lastName || "Doe";
  get fullName() { return self.firstName + " " + self.lastName; }
}
var mike = new Person({ firstName: "Mike", lastName: "Michaelson" });
document.write(mike.fullName);

这将引发一个异常:

未捕获的SyntaxError:意外的标识符

我尝试过其他选择,包括:

{ get fullName() { return self.firstName + " " + self.lastName; } }

和:

get this.fullName() { return self.firstName + " " + self.lastName; } 

和:

get self.fullName() { return self.firstName + " " + self.lastName; } 

但这些选择都不起作用。

这个工作:

function Person(data) {
  var self = this;
  self.firstName = data.firstName || "John";
  self.lastName = data.lastName || "Doe";
  
  Object.defineProperty(self, "fullName", { get: function () { return self.firstName + " " + self.lastName; } });
}
var mike = new Person({ firstName: "Mike", lastName: "Michaelson" });
document.write(mike.fullName);

但很明显,defineProperty的这种方式感觉很笨拙。

在构造函数函数中定义仅get属性的正确语法是什么?

我建议将其作为一个POJO,并一直传递选项,但您仍然会有Object.defineProperties的"笨拙",只是没有实际调用它的仪式(我个人更喜欢缩写)。

var Person = function (data) {
    if (data === undefined) {
        data = {};
    }
    data = _.defaults(data, {
        firstName: 'John',
        lastName: 'Doe'
    });
    return {
        get firstName() { return data.firstName; },
        get lastName() { return data.lastName; },
        get fullName() { return data.firstName + ' ' + data.lastName; }
    }
}

EDIT:现在我已经考虑了更多,我认为您想要包含defineProperty语法的原因是因为您想要对名字和姓氏具有读/写访问权限,但对fullName具有只读访问权限。如果这个假设是正确的,这就是我通常使用的模式。

var Person = function (data) {
    if (data === undefined) {
        data = {};
    }
    data = _.defaults(data, {
        firstName: 'John',
        lastName: 'Doe'
    });
    return {
        get firstName() { return data.firstName; },
        set firstName(name) { data.firstName = name; },
        get lastName() { return data.lastName; },
        set lastName(name) { data.lastName = name; },
        get fullName() { return data.firstName + ' ' + data.lastName; }
    }
}
p = Person();
p.fullName === 'John Doe'; // true
p.firstName = 'Jane';
p.fullName === 'Jane Doe'; // true

但是,需要注意一些注意事项,主要是对象引用。

data = { firstName: 'Jane' };
p = Person(data);
p.fullName === 'Jane Doe'; // true
data.lastName = 'Goodall';
p.fullName === 'Jane Doe'; // false!
console.log(p.fullName); // 'Jane Goodall'

我通常更喜欢将参数作为不可变的东西传递,或者通过将它们从对象中复制到不可变的对象中来冻结这些特性,这样通过对象引用进行更新就不会在你的行为中引起微妙的错误。