2017-02-13 47 views
4

我希望這些實例的原型相同,但以下相等性檢查的計算結果爲false。強制__proto__相等

var emp1 = new(EmployeeScope())("John"); 
var emp2 = new(EmployeeScope())("Amit"); 
var mgr1 = new(ManagerScope())("Robert", "Data"); 
var mgr2 = new(ManagerScope())("Alex", "Science"); 
emp1.getName() // John 
emp2.getName() // Amit 
mgr1.getDept() // Data 
mgr2.getDept() // Science 
mgr1.getName() // Robert 
mgr2.getName() // Alex 

emp1.__proto__ === emp2.__proto__ //false 
mgr1.__proto__ === mgr2.__proto__ //false 

function EmployeeScope() { 
    var name; 

    function Employee(newName) { 
    name = newName; 
    } 
    Employee.prototype.getName = function() { 
    return name 
    }; 
    Employee.prototype.setName = function(newName) { 
    name = newName 
    }; 
    return Employee; 
} 

function ManagerScope() { 
    var Employee = EmployeeScope(); 
    var dept; 

    function Manager(newName, newDept) { 
    new Employee(newName); 
    dept = newDept; 
    } 
    Manager.prototype = Object.create(Employee.prototype); 
    Manager.prototype.constructor = Manager; 
    Manager.prototype.getDept = function() { 
    return dept 
    }; 
    Manager.prototype.setDept = function(newDept) { 
    dept = newDept 
    }; 
    return Manager; 
} 
+5

我投票,因爲有關的編程風格和設計問題上codereview.stackexchange.com屬於關閉這一問題作爲題外話。 – Barmar

+0

好的,我刪除了這個問題。應該問codereview.stackexchange.com –

+0

好吧,堅持下去,有些東西不能按照你的要求工作,所以從這方面來說它屬於這裏。 – trincot

回答

1

的原因兩個對象有不同的原型是在構造函數EmployeeManager在你把它們放在包裝函數每次調用重新創建。因此,他們代表不同構造函數在包裝函數的不同調用中調用時。

讓對象方法訪問私有成員的常見解決方案是通過不是在原型上定義它們,而是在實例上定義它們。這樣,你可以在構造函數中定義範圍內它們:

function Employee(newName) { 
 
    var name = newName; 
 
    this.getName = function() { 
 
     return name 
 
    }; 
 
    this.setName = function(newName) { 
 
     name = newName 
 
    }; 
 
} 
 

 
function Manager(newName, newDept) { 
 
    var dept = newDept; 
 
    // Inherit from Employee 
 
    Employee.call(this, newName); 
 

 
    this.getDept = function() { 
 
     return dept 
 
    }; 
 
    this.setDept = function(newDept) { 
 
     dept = newDept 
 
    }; 
 
} 
 

 
var emp1 = new Employee("John"); 
 
var emp2 = new Employee("Amit"); 
 
var mgr1 = new Manager("Robert", "Data"); 
 
var mgr2 = new Manager("Alex", "Science"); 
 

 
console.log(emp1.getName()) // John 
 
console.log(emp2.getName()) // Amit 
 
console.log(mgr1.getDept()) // Data 
 
console.log(mgr2.getDept()) // Science 
 
console.log(mgr1.getName()) // Robert 
 
console.log(mgr2.getName()) // Alex 
 

 
console.log(Object.getPrototypeOf(emp1) === Object.getPrototypeOf(emp2)); 
 
console.log(Object.getPrototypeOf(mgr1) === Object.getPrototypeOf(mgr2));

注意,建議使用Object.getPrototypeOf()而不是__proto__。其次,你應該聲明局部變量爲var(或letconst),否則變量將被默默地聲明爲全局變量,並且每個員工都會得到相同的名稱。

+0

我曾想到這種方法。它改變getName()的輸出。所有對getName()的調用都會返回最後創建的員工的名稱.... –

+0

這是因爲在Employee構造函數的'name'聲明中缺少'var':它會變成一個全局變量。但是用'var'就可以。 – trincot

+0

謝謝......它的工作原理 –

1

也許是更容易理解他們爲什麼當你寫的代碼如下不共享相同的原型:

var EmployeeA = EmployeeScope(); 
var EmployeeB = EmployeeScope(); 
EmployeeA === EmployeeB // false 
EmployeeA.prototype === EmployeeB.prototype // false 
var emp1 = new EmployeeA("John"); 
var emp2 = new EmployeeB("Amit"); 
Object.getPrototypeOf(emp1) === EmployeeA.prototype // true 
Object.getPrototypeOf(emp2) === EmployeeB.prototype // true 

有您EmployeeScope建立在每一個新的呼叫ISN一個新的類(構造函數+原型)最好的主意。您也可以只使用它的一個實例,因爲name進行靜態存儲:

var emp3 = new EmployeeB("Dirk"); 
Object.getPrototypeOf(emp2) === Object.getPrototypeOf(emp3) // true 
emp2.getName() // Dirk - oops 

Manager類從,當然同樣的問題困擾。所以丟棄這些「範圍」功能,使他們的標準類:

function Employee(newName) { 
    this.name = newName; 
} 
Employee.prototype.getName = function() { 
    return this.name 
}; 
Employee.prototype.setName = function(newName) { 
    this.name = newName 
}; 


function Manager(newName, newDept) { 
    Employee.call(this, newName); 
    this.dept = newDept; 
} 
Manager.prototype = Object.create(Employee.prototype); 
Manager.prototype.constructor = Manager; 
Manager.prototype.getDept = function() { 
    return this.dept 
}; 
Manager.prototype.setDept = function(newDept) { 
    this.dept = newDept 
}; 

var emp1 = new Employee("John"); 
var emp2 = new Employee("Amit"); 
var emp3 = new Employee("Dirk"); 
var mgr1 = new Manager("Robert", "Data"); 
var mgr2 = new Manager("Alex", "Science"); 
Object.getPrototypeOf(emp1) === Employee.prototype // true 
Object.getPrototypeOf(emp2) === Employee.prototype // true 
Object.getPrototypeOf(emp3) === Employee.prototype // true 
Object.getPrototypeOf(mgr1) === Manager.prototype // true 
Object.getPrototypeOf(mgr2) === Manager.prototype // true 
+0

這種方法的問題在於它可以公開訪問名稱和部門屬性。能夠將變量保持爲私有是我將範圍內的函數封裝起來的主要動機。 –

+0

在這種情況下,[在*構造函數*](http://stackoverflow.com/a/13418980/1048572)中創建一個局部變量(帶'var'),而不是圍繞它的一些範圍。並且定義所有需要訪問它的方法,作爲構造函數範圍內的閉包。然而,鑑於有公共可用的setter和getter方法,保留'name'和'dept'「private」並不是必須的。而是放棄這些,只保留財產。簡單性規則:-) – Bergi

+0

Trincot的答案提出了同樣的方法。有用。非常感謝。 –