Подтвердить что ты не робот

Объектно-ориентированные вопросы в Javascript

Я использую javascript какое-то время, но никогда не изучал язык за пределами основ. Я читаю John Resig "Про Javascript Techniques" - я придумываю некоторые вопросы, но я не нахожу ответы на них в книге или на google и т.д.

Джон дает этот пример в своей книге:
Функция # 1

function User( name, age ){
  this.name = name;
  this.age = age;
}
// Add a new function to the object prototype
User.prototype.getName = function(){
  return this.name;
};
User.prototype.getAge = function(){
  return this.age;
};
var user = new User( "Bob", 44 );
console.log("User: " + user.getName() + ", Age: " + user.getAge());

Я все еще узнаю о свойстве прототипа, поэтому я попытался написать что-то похожее:
Функция # 2

function User (name, age ) {
  this.name = name;
  this.age = age;
  this.getName = function() {
    return this.name;
  };
  this.getAge = function() {
    return this.age;
  };
}
var user = new User( "Bob", 44 );
console.log("User: " + user.getName() + ", Age: " + user.getAge());

Он не использует свойство prototype для создания функций getName и getAge, но выход такой же, как пример Джона.

Я сделал еще один шаг и создал это:
Функция № 3

var User = {
  name: "",
  age: 0,
  setName: function(name) {
    this.name = name;
  },
  setAge: function(age) {
    this.age = age;
  },
  getName: function() {
    return this.name;
  },
  getAge: function() {
    return this.age;
  }
};
User.setName("Bob");
User.setAge(44);
console.log("User: " + User.getName() + ", Age: " + User.getAge());

Опять же - он выглядит иначе, чем пример Джона (и мне пришлось добавлять методы setter), но результат тот же.

Вопрос № 1 - в чем разница между тремя функциями? В чем преимущество свойства прототипа, и функция №2 делает что-то неправильно, потому что кажется, что более строгий код # 2 вместо # 1 (хотя я уверен, что # 1 делает это лучше, когда Джон создал его).

Вопрос № 2. Как мне изменить функцию № 3, чтобы не использовать методы setName и setAge, но сохраните {...} стенографию? Может ли сокращение {...} содержать конструкторы?

Заранее благодарим за помощь в изучении!

ИЗМЕНИТЬ Я думаю, что мой второй вопрос был немного запутанным. Я имел в виду, как я мог бы использовать {...} стенографию для создания объекта User, но затем после создания объекта скажу что-то вроде:

var user = new User("Bob", 44);

Как и в функции # 1 - или это невозможно?

РЕДАКТИРОВАТЬ # 2 Вау! Спасибо всем за потрясающие ответы. Это действительно делает его намного более понятным для меня. Поэтому, если я правильно понимаю, разница между # 1 и # 2 не слишком велика. Если я создаю только один объект "Пользователь", они, вероятно, совсем не отличаются друг от друга. Но если моя программа создает много объектов User, # 1, скорее всего, будет более эффективной и использовать меньше памяти, поскольку все объекты будут использовать одни и те же функции.

Я очень ценю все замечательные ответы - Спасибо!

4b9b3361

Ответ 1

Каждый раз, когда вычисляется функция() {}, создается новый объект функции. Поэтому в # 1 все объекты User совместно используют одни и те же функции getName и getAge, но в # 2 и # 3 каждый объект имеет свою собственную копию getName и getAge. Все разные функции getName ведут себя точно так же, поэтому вы не видите никакой разницы в выходе.

Сокращение {...} - это конструктор. При оценке он создает новый "объект" с заданными свойствами. Когда вы запускаете "новый пользователь (...)", он создает новый "пользователь". Вы создали объект с тем же поведением, что и пользователь, но они имеют разные типы.

Ответ на комментарий:

Вы не можете, прямо. Вы можете создать функцию, которая создает новый объект согласно # 3. Например:

function make_user(name, age) {
    return {
        name: name,
        age: age,
        getName: function() { return name; },
        getAge: function() { return age; },
    };
}

var user = make_user("Joe", "18");

Ответ 2

Если вы хотите сделать ООП в JavaScript, я бы предложил предложить закрыть закрытие. Я начал изучать эту тему с помощью этих трех веб-страниц:

http://www.dustindiaz.com/javascript-private-public-privileged/

http://www.dustindiaz.com/namespace-your-javascript/

http://blog.morrisjohns.com/javascript_closures_for_dummies

Различия между 1, 2 и 3 заключаются в следующем: 1) Является примером добавления новых методов к существующему объекту. 2) То же, что и # 1, за исключением того, что некоторые функции включены в объект в функции пользователя. 3) Является примером определения объекта с помощью JSON. Недостатком является то, что вы не можете использовать новый (по крайней мере, не тот пример), чтобы определить новые экземпляры этого объекта. Однако вы получаете преимущество от удобного стиля кодирования JSON.

Вы должны обязательно прочитать JSON, если вы еще этого не знаете. JavaScript будет иметь больше смысла, если вы поймете JSON.

изменить Если вы хотите использовать new в функции # 3, вы можете записать его как

function User() {
  return {
    name: "",
    age: 0,
    setName: function(name) {
      this.name = name;
    },
    setAge: function(age) {
      this.age = age;
    },
    getName: function() {
      return this.name;
    },
    getAge: function() {
      return this.age;
    }
  };
}

Конечно, все эти функции и свойства будут тогда публичными. Чтобы сделать их частными, вам нужно использовать закрытие. Например, вы можете сделать возраст и имя частным с помощью этого синтаксиса.

function User() {
  var age=0;
  var name="";
  return {
    setName: function(name_) {
      name = name_;
    },
    setAge: function(age_) {
      age = age_;
    },
    getName: function() {
      return name;
    },
    getAge: function() {
      return age;
    }
  };
}

Ответ 3

2

Вы можете получить доступ к имени и возрасту, не используя такие функции. В javascript вам нужно использовать разные хаки, чтобы сохранить что-то личное или защищенное.

Это

User.name = "BoB";
User.age = 44;

будет выдавать тот же результат, что и ваш пример.

Нет конструкторов, как они появляются на других языках. Самый простой способ - просто определить функцию init() и вызвать ее сразу после экземпляра объекта.

Но мой самый большой совет для вас - заглянуть в http://www.prototypejs.org/. Это javascript-библиотека с множеством интересных функций, которая пытается сделать javascript "больше OO *".

Используя библиотеку прототипов, вы можете сделать классы более похожими на реальные классы ООП. Он также имеет конструкторы.

Изменить: Что касается того, что вы просили в своем комментарии:

person = new User();
person.name = "Bob";
person.age = 44;

Ответ 4

В вашем примере # 1 показано использование свойства prototype. Это свойство доступно для всех создаваемых объектов javascript и позволяет добавлять свойства или функции к объявлению объекта, поэтому у вас есть объект с 2 свойствами, а позже вы добавили 4 функции (getters и seters).

Вы должны увидеть свойство prototype как способ изменения спецификации объекта во время выполнения, скажем, у вас есть объект с именем name:

var Name = {
  First: "",
  Last: ""
};

Вы можете использовать прототип для добавления функции getFullName() позже:

Name.prototype.getFullName = function() { return this.First + " " + this.Last; }

В примере 2 вы вставляете объявление этих геттеров и сеттеров в объявлении объекта, поэтому в конце они одинаковы. Наконец, на третьем примере вы используете обозначение объекта JavaScript, вы должны увидеть JSON.

О вашем вопросе 2 вы можете просто объявить свой объект как:

var User = {
  name: "",
  age: 0
};

это даст вам тот же объект без геттеров и сеттеров.

Ответ 5

Вопрос № 1

prototype имеет преимущество исправление обезьян. Как показывает первый пример, функция добавляется после факта. Вы можете продолжить это, чтобы добавить или заменить любые методы, которые вам нужны (хотя, с честным предупреждением).

Определение объектов, таких как # 2, больше соответствует строкам классического ООП. Но, опять же, исправление обезьян не разрешено на всех языках ООП.

Вопрос № 2

В вашей третьей функции вам даже не нужны функции get и set - name и age являются общедоступными (потенциальный недостаток {}).

var User = {
  name: "",
  age: 0
};

User.name = 'Bob';
User.age = 44;

console.log("User: " + User.name + ", Age: " + User.age);

Когда вы создаете объект, используя {} (литерал объекта), {} является конструктором (в зависимости от браузера). Но, по сути, нет, вы не можете использовать конструктор в этом формате.