JavaScript: для чего используются .extend и .prototype?

Я относительно новичок в JavaScript и продолжаю видеть .extend и .prototype в сторонних библиотеках, которые я использую. Я думал, что это связано с библиотекой JavaScript Prototype, но я начинаю думать, что это не так. Для чего они используются?

Ответ 1

Наследование Javascript основано на прототипе, поэтому вы расширяете прототипы таких объектов, как Date, Math и даже ваши собственные пользовательские.

Date.prototype.lol = function() {
 alert('hi');
};

( new Date ).lol() // alert message

В вышеприведенном фрагменте я определяю метод для всех объектов Date (уже существующих и всех новых).

extend обычно является функцией высокого уровня, которая копирует прототип нового подкласса, который вы хотите расширить из базового класса.

Итак, вы можете сделать что-то вроде:

extend( Fighter, Human )

И конструктор/объект Fighter наследует прототип Human, поэтому, если вы определяете такие методы, как live и die на Human, тогда Fighter также наследует их.

Обновлено разъяснение:

"функция высокого уровня" означает, что .extend не встроен, но часто предоставляется библиотекой, такой как jQuery или Prototype.

Ответ 2

.extend() добавляется многими сторонними библиотеками, чтобы упростить создание объектов из других объектов. Для некоторых примеров см. http://api.jquery.com/jQuery.extend/ или http://www.prototypejs.org/api/object/extend.

.prototype относится к "шаблону" (если вы хотите называть его) объекта, поэтому, добавляя методы к прототипу объекта (вы видите это в библиотеках, чтобы добавить в String, Date, Math, или даже функция) эти методы добавляются к каждому новому экземпляру этого объекта.

Ответ 3

Метод extend, например, в jQuery или PrototypeJS, копирует все свойства из источника в целевой объект.

Теперь о свойстве prototype, он является членом объектов функции, он является частью ядра языка.

Любая функция может использоваться как constructor для создания новых экземпляров объектов. Все функции имеют это свойство prototype.

Когда вы используете оператор new с объектом функции, будет создан новый объект, и он наследует его конструктор prototype.

Например:

function Foo () {
}
Foo.prototype.bar = true;

var foo = new Foo();

foo.bar; // true
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true

Ответ 4

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

Идея заключается в том, что существует базовый класс, а затем вы расширяете базовый класс, чтобы получить свойство, подобное наследованию (не полностью, но все же).

Вся идея состоит в том, чтобы понять, что означает прототип. Я не получил его, пока не увидел код Джона Ресига (рядом с тем, что jQuery.extend) написал блок кода, который делает это, и он утверждает, что библиотеки base2 и прототипов были источником вдохновения.

Вот код.

    /* Simple JavaScript Inheritance
     * By John Resig http://ejohn.org/
     * MIT Licensed.
     */  
     // Inspired by base2 and Prototype
    (function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};

  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);        
            this._super = tmp;

            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.prototype.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
  };
})();

Есть три части, которые выполняют работу. Сначала вы просматриваете свойства и добавляете их в экземпляр. После этого вы создаете конструктор для последующего добавления в объект. Теперь ключевые строки:

// Populate our constructed prototype object
Class.prototype = prototype;

// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;

Сначала вы указываете Class.prototype на нужный прототип. Теперь весь объект изменился, означая, что вам нужно заставить макет вернуться к своему.

И пример использования:

var Car = Class.Extend({
  setColor: function(clr){
    color = clr;
  }
});

var volvo = Car.Extend({
   getColor: function () {
      return color;
   }
});

Подробнее об этом читайте здесь Javascript Inheritance by John Resig.

Ответ 5

Некоторые функции extend в сторонних библиотеках более сложны, чем другие. Knockout.js, например, содержит минимально простой, который не имеет некоторых проверок, выполняемых jQuery:

function extend(target, source) {
    if (source) {
        for(var prop in source) {
            if(source.hasOwnProperty(prop)) {
                target[prop] = source[prop];
            }
        }
    }
    return target;
}

Ответ 6

  • .extends() создайте класс, который является дочерним для другого класса.
    за кулисами Child.prototype.__proto__ устанавливает значение Parent.prototype
    , поэтому методы наследуются.
  • .prototype наследует функции от одного к другому.
  • .__proto__ является геттером/сеттером для прототипа.