2017-02-13 3 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

Причина два объекта имеют разные прототипы в том, что функции конструктора Employee и Manager создаются снова при каждом вызове из оберток функций вы положили их. Таким образом, они представляют разные конструкторы при вызове в разных вызовах функций обертки.

Общее решение, позволяющее методам объектов обращаться к закрытым членам, определяется их не прототипом, а экземплярами. Таким образом, вы можете определить их в области конструкторы:

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 (или let, const), так как в противном случае переменная беззвучно объявлена ​​как глобальная переменная, и вы получите такое же имя для каждого сотрудника.

+0

Я думал об этом. Он изменяет вывод getName(). Все вызовы getName() возвращают имя последнего созданного сотрудника .... –

+0

Это потому, что в объявлении 'name' в конструкторе Employee отсутствует' 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

В этом случае [создайте локальную переменную (с 'var') в * конструкторе *] (http://stackoverflow.com/a/13418980/1048572), а не какую-то область вокруг нее. И определите все методы, которые должны получить к нему доступ как закрытие внутри области конструктора. Тем не менее, сохранение 'name' и' dept' «private» действительно не требуется, учитывая, что существуют общедоступные методы setter и getter. Скорее снимите их и сохраните только имущество. Правила простоты :-) – Bergi

+0

Тот же подход был предложен ответом Тринкота. Оно работает. Большое спасибо. –

Смежные вопросы