强迫__proto__平等

时间:2017-02-13 19:19:56

标签: javascript oop

我希望这些实例的原型相同,但以下等式检查的计算结果为false。

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;
}

2 个答案:

答案 0 :(得分:1)

两个对象具有不同原型的原因是构造函数EmployeeManager在每次调用包装函数时再次创建。因此它们代表不同< / em>在包装函数的不同调用中调用时的构造函数。

让对象方法访问私有成员的常见解决方案是,不是在原型上定义它们,而是在实例上定义它们。这样您就可以在构造函数范围中定义它们:

&#13;
&#13;
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)); 
&#13;
&#13;
&#13;

请注意,建议使用Object.getPrototypeOf()代替__proto__

其次,您应该使用var(或letconst)声明局部变量,因为否则该变量将被静默声明为全局变量,并且您将获得相同的名称为每个员工。

答案 1 :(得分: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在每次新的通话中创建一个新的类(构造函数+原型)并不是最好的主意。此外,您只能将它用于单个实例,因为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