2015-12-30 2 views
2

Я пытаюсь создать свойство только для чтения в функции конструктора с Javascript. Я ремикс the syntax I've found on 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); 

Это сгенерирует исключение:

Uncaught SyntaxError: Unexpected identifier

Я пробовал другие варианты, в том числе:

{ 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-только свойств внутри функций конструктора?

+0

Вы можете либо поместить его в 'prototype' (' object.prototype = {get x() {return this._x;}} '- но вы можете сделать это только один раз при объявлении полного прототипа) или использовать' defineProperty'. Если вы создаете свойство только для чтения, вы должны фактически использовать 'defineProperty', чтобы сделать его невозможным для записи. Это единственные действительные синтаксические способы сделать это. – somethinghere

+0

@ Jeroen вы ищете доступ для чтения/записи для имени/фамилии, но доступ только для чтения к 'fullName'? Если это так, пожалуйста, перечитайте мой ответ, поскольку я обновил его для размещения в таком случае. – Droogans

+0

@Droogans Спасибо за ваши идеи и мысли. Вы правильно поняли о доступе к чтению/записи, хотя я уже смог экстраполировать ваш первоначальный ответ на эти случаи.Я одобрил ваш ответ, это полезно, но это не совсем * ответ на мой вопрос, так как ваша функция «Личность»/больше не может использоваться как функция * constructor *, поскольку она нарушает наследование. - Угадайте, что я просто испорчен синтаксисом свойств C# ... – Jeroen

ответ

1

Я бы рекомендовал сделать это 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' 

Я обычно предпочитаю иметь аргументы, переданные в качестве чего-то неизменного, или замораживания тех черт, скопировав их из объекта и в нечто неизменное, так что обновления через ссылку на объект не вызывают тонкие ошибки в вашем поведении.

+0

Итак, «возможно ли использовать стенографию внутри самой функции конструктора»? На стороне примечания, в вашем примере, прототипом возвращенных POJO будет 'Object', а не' Person', правильно? – Jeroen

+0

Если вы запустите это и спросите 'Person.prototype', он скажет, что это объект' Person'. Вы также можете «новый», если хотите. Он должен вести себя точно так же, как ваш пример кода в вопросе, указанном выше. – Droogans

+0

'(new Person()) instanceof Person;' [является 'false' в сочетании с функцией' Person', которую вы отправили) (https://jsfiddle.net/jpxa0aj4/), в отличие от [объединения его с вопросом версия 'Person'] (https://jsfiddle.net/tqy6b887/). Возможно, я что-то недопонимаю? – Jeroen

Смежные вопросы