2014-10-03 71 views
0

是否可以在JavaScript類中調用父方法,但是仍然可以訪問父類和子類中的原型方法。下面是代碼示例:在JavaScript類中調用父方法,但可以訪問對象實例內的原型方法嗎?

var Base = function() { 

    this.baseMethod = function(){ 
    return 'baseMethod'; 
    }; 

    this.baseInitMethod = function() { 
    return 'baseInitMethod'; 
    } 
} 


Base.prototype.basePrototypeMethod = function() { 
    return "basePrototypeMethod"; 
}; 


var Specific = function() { 

    Base.call(this); 

    this.baseInitMethod = function() { 
    // call baseInitMethod from Base class 
    } 

    this.specificMethod = function(){ 
    return 'specificMethod'; 
    } 

    this.specificInitMethod = function() { 

    return this.basePrototypeMethod(); 
    } 
} 


Specific.prototype.specificPrototypeMethod = function() { 
    return 'specificPrototypeMethod' + '-' + this.baseInitMethod(); 
} 


for(var p in Base.prototype) { 
    Specific.prototype[p] = Base.prototype[p] 
} 


var s = new Specific(); 


console.log(s.baseMethod()); 

console.log(s.baseInitMethod()); 

console.log(s.basePrototypeMethod()); 

console.log(s.specificMethod()); 

console.log(s.specificInitMethod()); 

console.log(s.specificPrototypeMethod()); 

我想從baseInitMethod方法調用baseInitMethod在基類特殊類中,但讓所有的功能從上面仍然有效調用。那可能嗎?

+0

當然,你想要什麼休息繼承的約定?如果你想分享一個方法,創建一個可供兩者使用的第三個類。 – Alex 2014-10-03 12:00:30

+0

你能舉個例子嗎? – 2014-10-03 12:14:09

回答

1

Specific.prototype對象應Base.prototype對象繼承。目前你在複製其所有屬性的對象與此代碼:

for(var p in Base.prototype) { 
    Specific.prototype[p] = Base.prototype[p] 
} 

但實際上,應該使用Object.create建立一個真正的原型鏈

Specific.prototype = Object.create(Base.prototype); 

Specific.prototype.specificPrototypeMethod = function() { 
    return 'specificPrototypeMethod' + '-' + this.baseInitMethod(); 
} 

我想調用baseInitMethod中的baseInitMethod hod inside具體分類

是的。在你Specific構造函數,你首先需要獲得BasebaseInitMethod實例方法,您覆蓋實例的屬性之前:

function Specific() { 
    Base.call(this); 

    var parentInitMethod = this.baseInitMethod; 
    this.baseInitMethod = function() { 
     // call baseInitMethod from Base class: 
     parentInitMethod.call(this /*, arguments…*/); 
    } 

    … 
} 

,使所有功能從上面仍然有效調用。

我不確定你確切的意思。 specificPrototypeMethod將始終調用當前實例的baseInitMethod,這將覆蓋Specific而不是Base中定義的原始實例。

+1

Ohhhh man我覺得很愚蠢:)答案很簡單我只需要在重寫Specific方法中的方法之前創建對父方法的引用。太感謝了。現在我明白你爲什麼有106K代表。你是忍者:)再次感謝。 – 2014-10-03 13:50:12

1

以下是你需要做的:

var Base = function() { 
}; 
Base.prototype.baseMethod = function() { 
    return 'baseMethod'; 
}; 
Base.prototype.baseInitMethod = function() { 
    return 'baseInitMethod'; 
}; 
Base.prototype.basePrototypeMethod = function() { 
    return "basePrototypeMethod"; 
}; 


var Specific = function() { 
    Base.apply(this, arguments); 
}; 
Specific.prototype.baseInitMethod = function() { 
    Base.prototype.baseInitMethod.apply(this,arguments); 
}; 

Specific.prototype.specificMethod = function() { 
    return 'specificMethod'; 
}; 

Specific.prototype.specificInitMethod = function() { 
    var basePrototypeMethodCallResult = Base.prototype.basePrototypeMethod.apply(this,arguments); 

}; 
+0

我知道這一點。但是我不希望所有的方法都在原型中,因爲當你說新的Specific()時,所有在構造函數中的方法都會被重新創建,但是原型中的所有方法都不會被重新創建。確切地說, – 2014-10-03 12:09:01

+0

。如果你想在Base之外使用某種方法,你必須在它的原型中定義它。否則,它只是在Base類的實例範圍內定義的。 – jevgenig 2014-10-03 12:13:56

+0

btw:我沒有看到方法沒有被重新創建的問題。因爲它們仍然可以通過「this」實例訪問。另外 - 對於重新創建不必要的東西,在JS運行時期間不會重新創建它不是件好事嗎? ;) – jevgenig 2014-10-03 12:18:34

0

你覆蓋的BaseSpecificbaseInitMethod,與Specific的定義,那麼,爲什麼你會永遠想調用基版本?如果你只是刪除功能的覆蓋,你應該調用基定義:

var Base = function() { 

    this.baseMethod = function(){ 
    return 'baseMethod'; 
    }; 

    this.baseInitMethod = function() { 
    return 'baseInitMethod'; 
    } 
} 


Base.prototype.basePrototypeMethod = function() { 
    return "basePrototypeMethod"; 
}; 


var Specific = function() { 

    Base.call(this); 

    this.baseInitMethod(); // calls the Base definition only 

    this.specificMethod = function(){ 
    return 'specificMethod'; 
    } 

    this.specificInitMethod = function() { 

    return this.basePrototypeMethod(); 
    } 
} 
+0

我不能這樣做,因爲baseInitMethod被稱爲外部公共方法,所以我需要像定義一樣。 – 2014-10-03 13:34:22

+0

好吧,這很好,但你應該考慮避免這種過度設計的方法,因爲它是複雜的,幾乎肯定是不必要的。你標記爲正確的答案正好表明我在說什麼。 – Alex 2014-10-03 14:35:17

0

有人可能會爭辯說:「爲什麼總是試圖模仿'古典'的行爲,並與callapply大驚小怪,而不是接受原型委託模式呢?」

這裏是我的代碼:

var Base = { 

    baseVariable1: "baseValue1", 

    baseVariable2: "baseValue2", 

    baseMethod: function() { 
     return 'baseMethod'; 
    }, 

    baseInitMethod: function() { 
     return 'baseInitMethod'; 
    } 
} 

var Specific = Object.create(Base); 

Specific.variable1 = "value1"; 

Specific.variable2 = "value2"; 

Specific.specificInitMethod = function() { 
    return 'specificInitMethod' + '-' + this.baseInitMethod(); 
} 

Specific.specificMethod = function() { 
    return 'specificMethod' + '-' + this.baseInitMethod(); 
} 

var s = Object.create(Specific); 

console.log(s.baseInitMethod()); 

console.log(s.baseVariable1); 

console.log(s.baseVariable2); 

console.log(s.variable1); 

console.log(s.variable2); 

console.log(s.baseMethod()); 

console.log(s.specificInitMethod()); 

console.log(s.specificMethod()); 
+0

這種方法的問題是,我不能在基類內部有變量,而且我需要變量。 – 2014-10-03 13:35:33

+1

爲什麼你不能? – laruiss 2014-10-03 14:47:57

+0

當然你可以看到我編輯的答案。 JS中沒有課程。 (我認爲,即使使用ES6和'class'和'super'關鍵字,它也只是關鍵字來隱藏JS的真正原型性質)。 'Base'是一個對象。在我的情況下,它是一個普通的對象,所以你可以添加屬性,它可以指向函數,基元或普通對象。在你的,它是一個函數,但仍然是一個對象,因爲函數是JS中的對象,當然不是一個類。 – laruiss 2014-10-03 15:07:04

相關問題