//將obj2混入到obj1中,也稱obj1繼承自obj2function mix(obj1,obj2){ for(var k in obj2){ obj1[k] = obj2[k]; }}一般在混入的時候,都是混入的函數,所以考慮深拷貝的機會較少,在jq框架中,有一個方法叫 extend ,該方法實現 jq 中的混入。該方法具有的特征是:① 將多個對象混入到一個對象中mix ( dest, obj1, obj2, obj3, ... )② 實現深拷貝③ 實現原型式繼承④ 實現對象的構造(不使用構造函數創建對象)(3)在實際開發的時候,常常是這兩種方法混合使用(混合式繼承)在構造函數的原型上使用混入,那么原型對象就具有了很多方法屬性等成員,那么構造函數的實例對象就自動的繼承了這些成員,而且還有共享。// 1.準備一個構造函數function Role( name ) { this.name = name;}// 2.在原型中準備一個 extend 方法Role.PRototype.extend = function ( obj ) { // 將 obj 的成員混入到 原型對象中 for ( var k in obj ) { this[ k ] = obj[ k ]; }};// 3.盡情的擴展( 繼承 )// 為了簡單這么處理Role.skill = Role.prototype;// 法術攻擊Role.skill.extend({ fireBall: function () { console.log( '火球之術' ); }, bigFireBall: fucntion () ...});// 雷電 thunderRole.skill.extend({ qidoli: fucntion() { .... } ... });// 增加技能Role.skill.extend({ iceSkill: fucntion() { .... } ... });// 4.創建角色var sasigi = new Role( 'f' );2. 經典繼承語法
在ES5出現以前,就有人模擬了繼承的方式,就是使用一個對象,創建出另一個對象出來,保證被創建出來的對象的原型就是這個指定的對象。//調用該函數,可以創建一個繼承自參數給定的對象的對象function create(baSEObj){ function F(){} F.prototype = baseObj; return new F();}//可以創建一個對象,該對象繼承自一個數組var myArray = create( [] );//可以將myArray作為數組使用,是真數組/*增*/myArray.push('第一個被push進來的數據');myArray.unshift('第二個被unshift加入的數據');myArray[myArray.length++]='利用數組索引加入的數據';/*刪*/myArray.pop();//刪并返回最后一個myArray.shift();//刪并返回第一個myArray.splice(1,1);/*改*/myArray[1] = '哈哈哈';myArray.splice(1,1,'a','b','c');//從下標為1開始,刪掉1個元素,把后面的數據插入此位置/*查*/var i1 = myArray.indexOf('b');在較新的 ES5 的規范中已經內置了該算法,使用 Object.create 來實現該功能。所謂的簡單對象,首先要保證簡單,沒有多余的復雜數據:var obj = Object.create(null);console.log(obj); //空的簡單對象,里面什么都沒有沒有寫構造函數,obj 就是 Object 創建出來的。var obj = Object.create(base);//此時是一種特殊情況,obj 沒有構造函數,是內部創建的3. 比較高級的繼承方法
Object.create(base) => sub該方法有兩大缺點:① 沒有構造函數,無法復用② 沒有擴展,創建的子對象與父對象其實一模一樣,只是層級結構不同我們需要提供一個函數,滿足以下功能:① 可配置構造函數,由用戶決定構造函數應該如何定義② 可返回構造函數③ 應該有繼承要求可以配置,其實就是可以自己定義屬性和方法function createClass( options ){ return function(){ //這個函數就應該是最終的構造函數 }}由于需要重新配置構造函數的內容與原型,也要配置方法,可以讓 options 中必須帶有方法數據,因此代碼可以修改為另一種形式:function createClass( options ){ //要求 options中必須包含 constructor 和 methods //constructor是構造函數,它需要被返回 //methods是該對象應該具有的方法,應該將方法加到原型中 options.constructor.prototype = options.methods; return options.constructor;}簡單優化后:function createClass( options ){ var ctr = options.constructor; ctr.prototype = options.methods;//用替換原型的辦法 return ctr;}使用:屬性應該放在實例對象中,方法應該放在原型中。因此,兩個參數,第一個參數用于配置實例對象的成員,第二個參數用于描述原型。var Person = createClass({ constructor: function(name,age,gender){ this.name = name; this.age = age; this.gender = gender; }, methods: { sayHello: function(){ console.log( '你好,我是'+ this.name ); }, run: function(){ console.log( '你好,'+ this.name + '在跑' ); } }});var p = new Person('jim', 19, '男');p.sayHello();p.run();此時已經有Person了,希望再派生一個Student出來應該提供需要繼承的目標(對象?函數?)實現如下形式:那么將需要繼承的對象傳入要求options提供同一個base屬性,表明需要繼承誰代碼中的ctr的原型應該由base提供
function createClass( options ){ var ctr = options.constructor, base = options.base || Object.prototype; ctr.prototype = Object.create(base);//如果直接把base賦給原型,會出bug,派生對象中增加的東西在原型對象中也會增加 //方法的加入 for(var k in options.methods){ ctr.prototype[k] = options.methods[k]; } return ctr;}正確的(ctr.prototype = Object.create(base);):錯誤的(ctr.prototype = base;):
新聞熱點
疑難解答