JavaScript: для чего используются .extend и .prototype? - PullRequest
119 голосов
/ 23 сентября 2010

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

Ответы [ 5 ]

128 голосов
/ 23 сентября 2010

Наследование 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.

24 голосов
/ 23 сентября 2010

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

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

18 голосов
/ 12 декабря 2013

Похоже, что наследование 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 от Джона Ресига сообщение.

18 голосов
/ 23 сентября 2010

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

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

Любая функция может использоваться в качестве конструктора для создания новых экземпляров объектов,Все функции имеют это свойство 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
2 голосов
/ 14 марта 2017

Некоторые 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;
}
...