В чем разница между двумя объектами JavaScript? - PullRequest
4 голосов
/ 22 марта 2011

Я пытаюсь улучшить свои навыки JavaScript.Я не понимаю, почему (5) работает и (2) возвращает ошибку.Разве это не то же самое?

  1. B.fn () // OK
  2. B.fn2 () // Ошибка типа: у объекта # нет метода 'fn2'
  3. var a = new A ()
  4. a.fn () // OK
  5. a.fn2 () // OK

    var A = function () {
        this.fn = function () { alert(3); }
    }
    A.prototype = {
        fn2: function () { alert(4); }
    };
    
    var B =
        {
            fn: function () { alert(1); }
        }
    B.prototype = {
        fn2: function () { alert(2); }
    };
    

Ответы [ 4 ]

7 голосов
/ 22 марта 2011

a - это экземпляр класса A, где B - это сам класс.Поскольку fn2 не определена как статическая функция, она будет доступна только для экземпляра класса B в отличие от самого класса B.

Если вы хотите использовать B напрямую,Вы можете использовать:

new B().fn2()

, если вы определите B как function()

В качестве альтернативы, вы можете определить fn2 так же, как вы определилиfn

1 голос
/ 22 марта 2011

(простое объяснение) Свойство prototype применяется только при использовании function в качестве конструктора (с помощью оператора new). function создает клон его prototype, а ключевое слово this внутри функции устанавливается на клон. Свойства клона являются прямыми ссылками / указателями на свойства prototypes.

Литерал объекта {} является более мощным выражением, альтернативным new Object(), и поэтому «наследует» свойства от Object.prototype.

Итак:

function ClassLike() {}
ClassLike.prototype = {
    foo : "bar"
}

var instance = new ClassLike();
alert( instance.foo ); // bar

Работает, потому что оператор new запускает некоторые операции в движении, чтобы создать новый объект, тогда как:

var instance = {
    foo : "bar"
}
instance.prototype = {
    baz : "foobar"
}

Просто добавляет другое свойство (прототип) к уже созданному объекту, и никакой процесс не запускается для фактического назначения / изменения исходного прототипа объектов.

Теперь Mozilla добавила нестандартный (IE не поддерживает его) способ изменить прототип уже созданного объекта с помощью __proto__, и есть некоторые петиции, которые собираются добавить его в ES5 (EcmaScript 5). Я бы не стал его использовать. но это работает так:

var instance = {};
var parent = {
    foo : "bar"
}
instance.__proto__ = parent;

alert( instance.foo ); // bar

Еще один способ изменить прототип уже созданного объекта - добавить к прототипу конструкторов Object (что по многим причинам не рекомендуется). Как таковой:

var instance = {}; // a more powerful alternative to `new Object()`

Object.prototype.foo = "bar";

alert( instance.foo ); // bar

Это все возможно, хотя разумно было бы сделать это ... Я бы сказал, нет, но мнения разные, и я скорее избегаю дебатов;)

В любом случае, просто помните, что свойство prototype on работает, когда вы new a function, в противном случае оно просто становится свойством экземпляра.

0 голосов
/ 27 апреля 2013

Ну, ваш ответ довольно прост. В JavaScript только конструкторы имеют «прототипы», т.е. свойство prototype. Объектные литералы, например, "{}" нет. Следовательно, ваш номер 2 никогда не будет работать, если вы не измените его следующим образом:

var B = function(){ // the B constructor
          return this;
        }
B.prototype = {
fn2: function(){ alert(2); }
}
0 голосов
/ 22 марта 2011

То, что вы продемонстрировали, вызвано чем-то, что я считаю самой большой проблемой с ОО в JavaScript: прототип должен быть свойством функции конструктора, а не самого объекта. Это означает, что если у вас есть один объект, который можно легко определить как литерал объекта, вам все равно нужен бесполезный конструктор, чтобы просто определить прототип вашего объекта.

Прочтите эту статью: Прототип наследования в JavaScript Дугласа Крокфорда. Вот соответствующая часть:

[...] JavaScript сам по себе конфликтует о его прототипе. В прототипная система, объекты наследуют из предметов. JavaScript, однако, не хватает оператора, который выполняет это операция. Вместо этого он имеет new оператор, такой что new f() производит новый объект, который наследуется от f.prototype Эта косвенность была намеревался заставить язык казаться более знакомым классически обученным программисты, но не смогли этого сделать, так как мы можем видеть из очень низкого мнения Java программисты имеют JavaScript. Шаблон конструктора JavaScript сделал не обращение к классической толпе. Это также скрыл правду JavaScript прототипная природа. В результате там очень мало программистов, которые знают, как эффективно использовать язык. К счастью, легко создать оператор, который реализует истину наследование прототипа. Это стандартная функция в моем наборе инструментов, и я очень рекомендую его для вас.

Прочтите статью, чтобы узнать, как эффективно решить то, что вы пытаетесь сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...