Геттеры не работают в JavaScript

Я пытаюсь выяснить, что такое геттеры и сеттеры в JavaScript. Вот мой объект

  function User(fullName) {
        this.fullName = fullName;

        Object.defineProperties(this,{

            firstName :{
                get: function(){
                    return this.fullName.split(" ")[0];
                },
                set :function(value){
                    this.firstName = value;
                }
            },
            lastName:{
                get: function(){
                    this.lastName = this.fullName.split(" ")[1];
                },
                set: function(value){
                    this.lastName = value;
                }
            },
            fullName :{
                set: function(value){
                    this.fullName = value;
                }
            }
        });
}

Затем создает нового пользователя:

var user = new User("New User");

Но когда я пытаюсь получить свойство firstName, как

alert( user.firstName ) выдает ошибку "Не удается прочитать свойство split из undefined".

Что может вызвать проблему? Похоже, что 'this' не видно внутри функции get, но, насколько я понимаю, должно. Спасибо!

3 ответа

Решение

Вам не нужен сеттер для fullName как прямое назначение будет работать.

function User(fullName) {
  this.fullName = fullName || '';

  Object.defineProperties(this, {
    firstName: {
      get: function() {
        return this.fullName.split(" ")[0];
      },
      set: function(value) {
        this.firstName = value; // NOTE: This will throw an error
      }
    },
    lastName: {
      get: function() {
        return this.fullName.split(" ")[1];
      },
      set: function(value) {
        this.lastName = value; // NOTE: This will throw an error
      }
    }
  });
}

var joe = new User('John Doe');
var jane = new User('Jane Dane');
jane.fullName = 'Jane Doe';
document.write(
  '<pre>' + joe.firstName + '</pre>' +
  '<pre>' + jane.lastName + '</pre>'
);

Однако, как отмечено в комментариях к коду выше, вы не можете установить свойство на this с тем же именем, что и определенное свойство с установщиком. Например:

// defining `firstName`
firstName: {
  ...
  set: function(value) {
    this.firstName = value; // NOTE: This will throw an error
  }

Эта операция вызовет ошибку стека рекурсии, поскольку она будет постоянно пытаться обновить firstName поскольку this.firstName это сеттер.

Чтобы избежать этого, вы можете использовать локальные переменные в функции-конструкторе и сделать что-то вроде:

function User(fullName) {
  var firstName;
  var lastName;

  Object.defineProperties(this, {
    firstName: {
      get: function() {
        return firstName;
      },
      set: function(value) {
        return (firstName = value);
      }
    },
    lastName: {
      get: function() {
        return lastName;
      },
      set: function(value) {
        return (lastName = value);
      }
    },
    fullName: {
      get: function() {
        return firstName + ' ' + lastName;
      },
      set: function(value) {
        var names = value && value.split(' ');
        firstName = names[0];
        lastName = names[1];
      }
    }
  });
  
  if (fullName) {
    this.fullName = fullName;
  }
}

var joe = new User('John Doe');
var jane = new User('Jane Dane');
jane.lastName = 'Doe';
document.write(
  '<pre>' + joe.firstName + '</pre>' +
  '<pre>' + jane.lastName + '</pre>'
);

Некоторые проблемы / изменения, необходимые для вашего кода:

  1. this.fullName.split ("") [0]; => попытается вызвать getFullName, поскольку fullName определено как свойство. Поскольку вы не определили getFullName, это приводит к ошибке
  2. Скажем, вы идете вперед и определяете геттер для fullName:

    get: function () {return this.fullName; }

    Это создаст стекопоток, так как this.fullName заканчивается рекурсивным вызовом getFullName()

  3. Правильный способ его использования (конечно, обновите сеттеры, чтобы сделать что-то полезное):

function User(fullName) {
    this.fullName = fullName;
    Object.defineProperties(this, {

        firstName: {
            get: function () {
                return this.fullName.split(" ")[0];
            },
            set: function (value) {
                this.firstName = value;
            }
        },
        lastName: {
            get: function () {
                return this.fullName.split(" ")[1];
            },
            set: function (value) {
                this.lastName = value;
            }
        }
    });
}
var user = new User("New User");
alert( user.firstName );

У fullName нет получателя, поэтому он возвращает неопределенный

получить

Функция, которая служит геттером для свойства, или неопределенная, если нет геттера. Функция return будет использоваться в качестве значения свойства.

По умолчанию не определено.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Другие вопросы по тегам