简体   繁体   中英

can someone explain function.prototype.call() and function.prototype=Object.create() to me?

I understand how to write proper inheritance but I'm trying to understand exactly what I'm doing when I'm writing this so I fully understand my code. I have read a bit of the MDN but I'm not fully understanding it, help would be greatly appreciated, thanks I'm a bit confused

I understand that I'm supposed to write inheritance like this

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

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

From my understanding function.call works similar to this, so when you this as a arg it changes to where arg1 points for example, it basically allows you to change were 'this', points to

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

So function.call doesn't create inheritance because it simply copies the properties to the new function and object and doesn't force it to walk up the prototype chain so you're repeating your self and from my understanding then its only use would to to copy arguments from another function.

this quasi-inheritance works if I just use Function.call with constructors, that is if I simply copy the values into a new object, as such

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

From my understanding Object.create(function.prototype) creates a new object so its no referencing the original functions prototype and create inheritance, this works and creates inheritance like I would expect, where it walks up a prototype chain and doesn't copy the properties into a new object

   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

however this doesn't seem to work with constructor functions so I'm a bit confused as to what I am doing wrong or what the purpose of function.prototype=Object.create(super Function.prototype); That is you cant seem to use inheritance from my experience to create a prototype chain, for example the following wouldn't work for me

  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()

So it seems to me this isn't doing anything, so what am I missing, what am I doing wrong and if I'm not doing anything wrong what is the purpose and what am I not understanding? The only way I can get it to work is with using Function.call and it seems to work the same way with or without function.prototype=Object.create(super function.prototype);, but it would be preferably if it walked up a prototype chain so to code dry.

call allows you to explicitly set what this will be.

The point of Employee.call(this); is to extend the Manager currently being created ( this ) with the properties all Employee s have.

While in a sense you are inheriting the attributes, this part has nothing to do with JavaScript's prototypical inheritance . It's just a neat way of achieving this:

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

however this doesn't seem to work with constructor functions so I'm a bit confused as to what I am doing wrong or what the purpose of function.prototype=Object.create(super function.prototype); for example the following wouldn't work for me

 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 

First of all, you are not supposed to access Manager.pay directly if you meant to use it as a constructor . Secondly, you are missing the call part here, and that's the reason your instances won't have the pay and depth properties.

Here is a working example:

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

And finally for the purpose of F.prototype=Object.create(Super.prototype); .

Note that the previous example would work if you assigned the prototype directly, like this

Manager.prototype = Employee.prototype;

This is essentially what you want to achieve - whenever an instance of Manager can't find its own property, it should look for it within the prototype of Employee .

The problem arrives once you start extending the prototype of the Manager . Say you want to add a function fireEmployee to managers. Normally you'd do

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

but your Manager.prototype and Employee.prototype are the same object. There is no way to add properties to only one of them, without effect to the other.

That's why you use Object.create . You create an empty object which will store all the extensions specific for managers, and that object's prototype is Employee.prototype .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM