【问题标题】:can someone explain function.prototype.call() and function.prototype=Object.create() to me?有人可以向我解释 function.prototype.call() 和 function.prototype=Object.create() 吗?
【发布时间】:2016-11-05 07:11:26
【问题描述】:

我了解如何编写正确的继承,但我试图准确了解我在编写此代码时所做的事情,以便完全理解我的代码。我已经阅读了一些 MDN,但我并不完全理解它,非常感谢您的帮助,谢谢我有点困惑

我知道我应该这样写继承

 function Employee(){
      this.pay=' ';
      this.dept=' ';
 }

 function Manager(){
     Employee.call(this);
     this.reports=[];
 }
 Manager.prototype=Object.create(Employee.prototype);

据我了解,function.call 的工作方式与此类似,所以当你 this 作为 arg 它会更改为 arg1 指向的位置,例如,它基本上允许您更改为 'this',指向

  function Employee(context,arg1,arg2,arg3){
     context.arg1=arg1;
     context.arg2=arg2;
     context.arg3=arg3;
  }

所以 function.call 不会创建继承,因为它只是将属性复制到新的函数和对象,并且不会强制它沿着原型链向上走,所以你在重复你自己,根据我的理解,它是唯一的使用 will to 从另一个函数中复制参数。

如果我只是将 Function.call 与构造函数一起使用,则此准继承有效,也就是说,如果我只是将值复制到一个新对象中,就像这样

  function Employee(){
       this.pay=' ';
       this.dept=' ';
   }
  function Manager(){
      Employee.call(this);
      this.reports=[];
  }
  //this works!!
 /*but all the objects created with Manager() will have all the properties   from Employee copied directly into it, and it doesnt walk the prototype chain to find them*/

据我了解,Object.create(function.prototype) 创建了一个新对象,因此它不引用原始函数原型并创建继承,这可以像我期望的那样工作并创建继承,它沿着原型链向上走并且没有t 将属性复制到新对象中

   var animal={
       moves: true
    }

   var snake = Object.create(animal);
       snake.noLeggs=true;
       snake.coldBlooded= true;

   var python= Object.create(snake);
       python.size='large';
    //if I were to type python.moves it would return true
   //but python doesn't have a property named pay so its walking up the prototype chain to find it

但是这似乎不适用于构造函数,所以我对我做错了什么或 function.prototype=Object.create(super Function.prototype); 的目的有点困惑那就是您似乎无法使用我的经验继承来创建原型链,例如以下内容对我不起作用

  function Employee(){
       this.pay=' ';
       this.depth=' ';
  }

  function Manager(){
      this.reports=[];
  }
  Manager.prototype=Object.create(Employee.prototype);
  //however if I were to type var tom= new Manager(); tom.pay, pay would return "undefined"
  //so it appears I need Function.call()

所以在我看来这没有做任何事情,所以我错过了什么,我做错了什么,如果我没有做错任何事情,目的是什么,我不明白什么?我可以让它工作的唯一方法是使用 Function.call 并且无论有没有 function.prototype=Object.create(super function.prototype); 似乎都以相同的方式工作,但最好是它走起来一个原型链,这样代码就干了。

【问题讨论】:

    标签: javascript performance prototype


    【解决方案1】:

    call 允许您明确设置this 的内容。

    Employee.call(this); 的意义在于扩展当前正在创建的Manager (this) 与所有Employees 所具有的属性。

    虽然在某种意义上您是在继承属性,但这部分与 JavaScript 的原型继承无关。这只是实现这一目标的一种巧妙方法:

    function fillEmployee( employee ){
      employee.pay=' ';
      employee.dept=' ';
    }
    function Employee(){
      fillEmployee(this);
    }
    function Manager(){
      fillEmployee(this);
      this.reports=[];
    }
    

    但是这似乎不适用于构造函数,所以我是 有点困惑我做错了什么或目的是什么 function.prototype=Object.create(super function.prototype);为了 以下示例对我不起作用

    function Employee(){
      this.pay=' ';
      this.depth=' ';
    }
    
    function Manager(){
      this.reports=[];
    }
    
    Manager.prototype=Object.create(Employee.prototype);
    //if I were to type Manager.pay it would return undefined
    

    首先,如果您打算将Manager.pay 用作构造函数,则不应该直接访问它。其次,您在这里缺少 call 部分,这就是您的实例没有 pay 和 depth 属性的原因。

    这是一个工作示例:

    function Employee() {
      this.pay = ' ';
      this.depth = ' ';
    }
    
    function Manager() {
      Employee.call(this);
      this.reports = [];
    }
    Manager.prototype = Object.create(Employee.prototype);
    
    var peter = new Manager();
    console.log(peter.pay);

    最后是为了F.prototype=Object.create(Super.prototype);

    请注意,如果您像这样直接分配原型,则前面的示例将起作用

    Manager.prototype = Employee.prototype;
    

    这本质上就是您想要实现的 - 每当Manager 的实例找不到它自己的属性时,它应该在Employee 的原型中寻找它。

    一旦你开始扩展Manager 的原型,问题就来了。假设您想向经理添加功能fireEmployee。通常你会这样做

    Manager.prototype.fireEmployee = function(){ ... }
    

    但是您的 Manager.prototypeEmployee.prototype 是同一个对象。没有办法只为其中一个添加属性,而不影响另一个。

    这就是您使用Object.create 的原因。您创建一个空对象,该对象将存储特定于管理器的所有扩展,并且该对象的原型是 Employee.prototype

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-08
      • 2012-04-09
      • 2021-02-18
      • 2021-01-05
      • 1970-01-01
      • 2023-02-08
      • 2011-01-08
      • 2014-04-20
      相关资源
      最近更新 更多