может кто-то объяснить функцию.прототип.вызов () и функция.объект прототипа.create () to me?

Я понимаю, как написать правильное наследование, но я пытаюсь понять, что именно я делаю, когда я пишу это, чтобы я полностью понял свой код. Я прочитал немного MDN, но я не полностью понимаю его, помощь была бы очень признательна, спасибо я немного запутался

Я понимаю, что я должен писать наследство так

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

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

Из моего понимания функции.вызов работает аналогично этому, поэтому когда вы
это как arg он изменяется, где arg1 указывает, например, это в основном позволяет изменить были «это», указывает на

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

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

это квази-наследование работает, если я просто использую функцию.вызовите конструкторы, то есть если я просто скопирую значения в новый объект, как таковой

  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*/

Из моего понимания объекта.create (function.prototype) создает новый объект, поэтому его отсутствие ссылки на исходный прототип функций и создание наследования, это работает и создает наследование, как я ожидал бы, где он идет вверх по цепочке прототипов и не копирует свойства в новый объект

   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

однако это не похоже на работу с функциями конструктора, поэтому я немного запутался в том, что я делаю неправильно или какова цель функции.объект прототипа.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()

Поэтому мне кажется, что это ничего не делает, так что я упускаю, что я делаю неправильно, и если я ничего не делаю неправильно, какова цель и чего я не понимаю? Единственный способ заставить его работать — это использовать функцию.вызовите и кажется, что работает такой же путь с или без функции.объект прототипа.create (super function.prototype);, но было бы предпочтительно, если бы он подошел к цепи прототипа так, чтобы код был сухим.

1 ответ

  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=[];
    }
    

    однако это, похоже, не работает с функциями конструктора, поэтому я
    немного запутался о том, что я делаю неправильно или что цель
    функция.объект прототипа.create (super function.прототип); для
    пример следующий не будет работать для меня

    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.prototypeи Employee.prototypeявляются одним и тем же объектом. Невозможно добавить свойства только к одному из них, не влияя на другие.

    Вот почему вы используете Object.create. Вы создаете пустой объект, который будет хранить все расширения, определенные для менеджеров ,и прототипом этого объекта являетсяEmployee.prototype.