2012-08-16 3 views
7

Я разработчик javascript с умеренным уровнем, который пытается понять, как работает базовая библиотека внутри, и будет глубоко признателен, если кто-то поможет мне решить некоторые проблемы.Объясните базовый объект и шаблон создания класса

так вот что я понимаю

основного определения функции конструкторы в Магистральном

Backbone.Model = function(attributes, options) { } 

затем они используют общую цель расширить метод, чтобы добавить общие черты в прототипе нашего конструктора.

_.extend(Backbone.Model.prototype, Backbone.Events, {...}) 

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

var user = new Backbone.Model() 

и это часть я нахожу сложным

Конечно, это не так, как мы создаем объект в магистральной системе, но мы используем метод расширения

var Users = Backbone.Model.extend({}); 
var user = new Users() 

и становой кода

Backbone.Model.extend = extend; 

var extend = function(protoProps, classProps) { 
     var child = inherits(this, protoProps, classProps); 
     child.extend = this.extend; 
     return child; 
}; 

var inherits = function(parent, protoProps, staticProps) { 
    var child; 
    if (protoProps && protoProps.hasOwnProperty('constructor')) { 
     child = protoProps.constructor; 
    } else { 
     child = function() { 
      return parent.apply(this, arguments); 
     }; 
    } 
    _.extend(child, parent); 
    ctor.prototype = parent.prototype; 
    child.prototype = new ctor(); 
    if (protoProps) _.extend(child.prototype, protoProps); 
    if (staticProps) _.extend(child, staticProps); 
    child.prototype.constructor = child; 
    child.__super__ = parent.prototype; 
    return child; 
}; 

пожалуйста, объясните мне, что происходит внутри наследуют функции и какова польза от расширения метода подход

+0

Магистраль имеет источник с комментариями: http://documentcloud.github.com/backbone/docs/backbone.html Поиск по наследует метод. У них хорошее описание. – jForrest

ответ

10

extend функция Underscore сливается членов (функции и свойства) из второго аргумент в первый. Например:

var reciever = { 
    name: "Jonny", 
    age: 29 
}; 

var supplier: { 
    languages: [ "javascript", "actionscript" ]; 
    sayHi: function() { 
     console.log("Hi, name name is " + this.name); 
    } 
}; 

_.extend(receiver, supplier); 

После выполнения приведенного выше кода, объект-получатель будет был дополнен (изменен), и теперь выглядеть следующим образом:

/* 
    { 
     age: 29, 
     languages: [ "javascript", "actionscript" ], 
     name: "Jonny", 
     sayHi: <<function>> 
    } 
*/ 
console.dir(receiver); 

Обратите внимание, что объект поставщиком остается неизменным и объекта-приемника получает все свойства и функции от поставщика. Этот процесс обычно называют mixin и используется, чтобы избежать необходимости повторного использования функций (как часть более широкого принципа программирования знать DRY - Don't Repeat Yourself).

Теперь, как для Model.extend функции Магистральной, она действует как factory method вернуть вам Конструктора функцию, которые могут быть использованы для создания новых экземпляров модели с внутренней inherits функции делает большую часть работы. Функция inherits принимает концепцию mixin на один шаг вперед, создает inheritance chain между предоставленным объектом и родительским (в данном конкретном случае объектом Backbone.Model).

var child; 
if (protoProps && protoProps.hasOwnProperty('constructor')) { 
    child = protoProps.constructor; 
} else { 
    child = function() { 
     return parent.apply(this, arguments); 
    }; 
} 

Этот первый блок кода пытается найти функцию-конструктор внутри хэша поставляемого объекта; если он отсутствует, он создает для вас новую функцию конструктора, которая автоматически передает предоставленные аргументы Backbone.Model собственным constructor function.

_.extend(child, parent); 

Далее мы называем подчеркнуть расширят метод подмешать все свойства и функцию из прилагаемого хэша свойств и функций в функцию конструктора; это гарантирует, что каждый созданный вами экземпляр имеет свои собственные данные (например: свойства не являются статическими и совместно используются во всех создаваемых вами экземплярах).

ctor.prototype = parent.prototype; 
child.prototype = new ctor(); 
if (protoProps) _.extend(child.prototype, protoProps); 
if (staticProps) _.extend(child, staticProps); 
child.prototype.constructor = child; 
child.__super__ = parent.prototype; 

Этот последний блок является самым захватывающим и создает связь между прототипом недавно созданной функцией конструкторы и родительским прототипом (Backbone.Model) объекта. Таким образом, все новые экземпляры, возвращаемые конструктором, будут содержать обычные базовые методы модели (то есть: get и set), поскольку они разрешены из цепи прототипа. Если вы хотите узнать больше об этом конкретном блоке кода, то Douglas Crockford's article on Prototypal inheritance - отличное место для начала.

Суть этого подхода заключается в том, что она позволяет поставить хэш свойства и функции, полученная функция Constructor будет использовать как основу, например:

var Person = Backbone.Model.extend({ 
    name: "Jon Doe", 
    sayHi: function() { 
     console.log("Hi, my name is " + this.get("name")); 
    } 
}); 

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

var dave = new Person(); 
dave.sayHi(); // "Hi, my name is Jon Doe" 

dave.set("name", "Dave"); 
dave.sayHi(); // "Hi, my name is Dave" 

// You can also supply properties when invoking the constructor. 
var jimmy = new Person({ name: "Jimmy" }); 
jimmy.sayHi(); // "Hi, my name is Jimmy" 
+0

спасибо за замечательное объяснение, хотя я до сих пор совершенно запутался с этим блоком кода 'если (protoProps && protoProps.hasOwnProperty («конструктором»)) { ребенка = protoProps.constructor; } ' Не всегда ли это объект, а какой смысл его использовать. 'else { child = function() { return parent.apply (this, arguments); }; } ' и этот блок кода так же, как возвращение Backbone.Model (родитель, protoProps, staticProps) который снова сбивает с толку, как объект аргумент будет иметь родительский параметр Что вред при использовании только ' ребенок = функция() {} ' –

+0

Если заданная основа будет использовать вашу конструкторскую функцию. в противном случае он будет использовать конструктор модели Backbone. этот конструктор также должен знать аргументы passt для объекта. поэтому вам нужно вызвать родительский конструктор с методом parent.apply. –

Смежные вопросы