2012-08-16 34 views
7

我是一位中等水平的JavaScript開發人員,他試圖理解骨幹庫如何在內部工作,並且如果有人幫助我解決一些挑戰,我會深表感謝。解釋骨幹對象和類創建模式

所以在這裏我是這樣理解的骨幹

構造函數的基本定義是

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

然後,他們使用的通用擴展方法在我們的構造函數的原型加上共同的特點。

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

即日起至這一部分,我確切地知道發生什麼事,但下面的代碼

var user = new Backbone.Model() 

樂意實例化新的對象,這是我發現有挑戰性

部分當然這不是我們在Backbone中實例化對象的方式,但我們使用擴展方法

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 2012-08-16 14:12:22

回答

10

下劃線的extend功能從第二合併成員(功能和性能)爭論進入第一。例如:

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); 

接下來,我們稱之爲強調的延伸的方法來從MIXIN屬性和功能到構造功能的提供的散列所有屬性和功能;這可確保您創建的每個實例都擁有自己的數據(例如:屬性不是靜態的,並在您創建的所有實例中共享)。

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)對象的原型之間的關係。通過這樣做,構造函數返回的所有新實例將包含通常的主幹模型方法(即:getset),因爲它們是從原型鏈中解析出來的。如果你想了解更多關於這塊特定的代碼,Douglas Crockford's article on Prototypal inheritance是一個很好的開始。

這種方法的一點是,它允許您提供其產生的構造函數將作爲藍本使用屬性和功能的哈希值,例如:

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

感謝您的精彩解釋,儘管我仍然很困惑這段代碼 'if(protoProps && protoProps.hasOwnProperty('constructor')) { child = protoProps.constructor; } 是不是總是對象和使用它的重點。 'else {child} = function(){ return parent.apply(this,arguments); }; }' 和這個代碼塊是相同返回Backbone.Model(父,protoProps,staticProps) 這又是混亂作爲參數對象將具有父參數 什麼在使用危害只是 '孩子=()的函數{}' – 2012-08-16 17:49:15

+0

如果定義的主幹將使用您的構造函數。否則它將使用Backbone的模型構造函數。這個構造函數也需要知道向對象傳遞的參數。因此您需要使用parent.apply方法調用父類構造函數。 – 2014-10-29 08:41:03