-2

我設法創建了一個名爲「createHumanByGender」的類似工廠的函數,但是,返回的對象不允許我調用其原型方法「Human.prototype.getFullName( )」。 爲什麼會有這種情況發生?未通過工廠返回的JavaScript對象原型

代碼如下:

// get female instance of Jade 
var jade = createHumanByGender.bind(this, 'Female', 'Jade', 'Taylor')(); 
console.log(jade.getFullName()); 


// ------------------------------------------------ 
// HUMAN 
function Human (forename, surname) { 
    this.forename = forename; 
    this.surname = surname; 
    this.age = 0; 
} 

Human.prototype = { 
    getForename : function() { 
     return this.forename; 
    }, 
    getSurname : function() { 
     return this.surname; 
    }, 
    getFullName : function() { 
     return this.forename + ' ' + this.surname; 
    } 
}; 


// MALE 
function Male (forename, surname) { 
    Human.call(this, forename, surname); 
    this.gender = 'Male'; 
} 
Male.prototype = Object.create(Human.prototype); 


// FEMALE 
function Female (forename, surname) { 
    Human.call(this, forename, surname); 
    this.gender = 'Female'; 
} 
Female.prototype = Object.create(Human.prototype); 


// GENDER 
function createHumanByGender (gender, forename, surname) { 
    return new this[gender](forename, surname); 
} 
+0

請顯示調用'createHumanByGender()'的代碼,然後嘗試在返回的對象上執行方法的代碼。 – jfriend00

+0

你確定你調用它正確嗎?像這樣'var h = createHumanByGender('Male','Thomas','Mann'); h.getFullName();'。 – dfsq

+0

你在哪裏運行這段代碼?按照你的方式使用'this'的一個問題是,在沙箱中你的'Human/Male/Female'函數定義可能存在於非全局範圍中,但是this'仍然是隱式的全局對象。嚴格模式也會毀了你的一天。什麼錯誤被拋出? – Oka

回答

0

在你的代碼,你的代碼運行指派從原型prototype所以你的對象沒有繼承方法之前調用構造函數。將您的調用移至工廠函數,以在構造函數的定義之後。

此外,使用this的方式通常是不好的做法,因爲它可能無法在嚴格模式下工作。直接引用window就是您想要的,或者將您的構造函數作爲某些名稱空間對象的屬性並直接在該對象上查找它們。

這個版本的代碼的工作(工作demo here):

// ------------------------------------------------ 
// HUMAN 
function Human (forename, surname) { 
    this.forename = forename; 
    this.surname = surname; 
    this.age = 0; 
} 

Human.prototype = { 
    getForename : function() { 
     return this.forename; 
    }, 
    getSurname : function() { 
     return this.surname; 
    }, 
    getFullName : function() { 
     return this.forename + ' ' + this.surname; 
    } 
}; 


// MALE 
function Male (forename, surname) { 
    Human.call(this, forename, surname); 
    this.gender = 'Male'; 
} 
Male.prototype = Object.create(Human.prototype); 


// FEMALE 
function Female (forename, surname) { 
    Human.call(this, forename, surname); 
    this.gender = 'Female'; 
} 
Female.prototype = Object.create(Human.prototype); 


// GENDER 
function createHumanByGender (gender, forename, surname) { 
    var f = this[gender]; 
    return new f(forename, surname); 
} 

// get female instance of Jade 
var jade = createHumanByGender.bind(this, 'Female', 'Jade', 'Taylor')(); 
console.log(jade.getFullName()); 

僅供參考,我建議你改變你的工廠函數來此:

// GENDER 
function createHumanByGender (gender, forename, surname) { 
    var f = window[gender]; 
    return new f(forename, surname); 
} 

而且,當時這樣稱呼它:

// get female instance of Jade 
var jade = createHumanByGender('Female', 'Jade', 'Taylor'); 
console.log(jade.getFullName()); 

僅供參考,如果您真的想要導致this在您要立即致電的功能中,您可以使用.call()而不是.bind() - 但這裏不需要。

+0

更改了我的答案,以便在將任何內容分配給'prototype'之前包含有關運行構造函數的主要問題。 – jfriend00

+0

'返回新的[性別](姓,名);'應該沒有額外的括號,或中間工作正常。屬性查找的優先級高於運算符new和函數調用的優先級。 [實施例](https://jsfiddle.net/krzczsL6/)。 – Oka

+0

@Oka - 是的,你說得對。我從我的答案中刪除了這些。就我個人而言,我不喜歡那種依賴於代碼讀者的東西來了解詳細的優先規則,以準確地理解它所做的或者它是否正確。我寧願編寫可以更容易理解的代碼。 – jfriend00