This is the 10th day of my participation in the August Gwen Challenge. For details, see: August Gwen Challenge juejin.cn/post/698796…

New fundamentals

The main role

Executes a constructor that returns a new instance object.

During execution, the constructor’s parameters are used to determine whether the parameters need to be passed.

step

  • Create a new object
  • Assign the constructor’s scope to the new object
  • Execute the code in the constructor
  • Return a new object
var ObjectFactory = function () {
    // Create an object
    var obj = new Object(a)// Return the first argument as a constructor
    var Constructor = [].shift.call(arguments)
    // Copy the constructor's prototype to the object's prototype
    obj.__proto__ = Constructor.prototype
    // Call the constructor with obj as this, arguments
    var ret = Constructor.apply(obj, arguments)
    If the constructor returns an object, it returns it directly, otherwise we return the object created by this (new)
    return typeof ret === 'object'? ret: obj
}
// The effect is equivalent
var a = ObjectFactory(Person, 'sven');Copy the code

Pay attention to the point

  • No new is used and the constructor returns no value

    • Equivalent to normal function execution, where this points to window
  • The constructor has a return value

    • Return an object

      • Because new requires that an object must be returned, if an object unrelated to this is returned, the final value will be that object and not the this object generated by new
      function Person(){
         this.name = 'Jack'; 
         return {age: 18}}var p = new Person(); 
      console.log(p)  // {age: 18}
      console.log(p.name) // undefined
      console.log(p.age) / / 18
      Copy the code
  • It’s not an object

    • It also returns the newly generated this object, following the implementation steps of New

The new keyword always returns an object after execution, either an instance object or an object specified by the return statement.

Basic principles of apply, call, and bind

Basic situation

Call, apply, and bind are the three methods that hang on the Function object and must be called by a Function.

The basic grammar

func.call(thisArg, param1, param2, ...) func.apply(thisArg, [param1,param2,...] ) func.bind(thisArg, param1, param2, ...)Copy the code

The difference between

  • Similarities: Both can change the this reference of func.

  • Difference:

    • The difference between call and apply is that the call is written differently:

      • The second argument to apply is an array;
      • Call is passed to func from the 2nd to the NTH;
    • Bind is different from these two,

      • Bind changes the this direction of func, but not immediately
      • These two (call and apply) are executed immediately after changing the this direction of the function.

Usage scenarios

Determine the data type

function getType(obj){
 let type = typeof obj;
 if(type ! = ="object") {return type;
 }
 return Object.prototype.toString.call(obj).replace(/^[Object (\S+)]$/.'$1');
}
Copy the code

Call borrows the toString method for data type determination

Class arrays borrow array methods

Class arrays are not real arrays, so they cannot use array methods. They can only be borrowed by call

var arrayLike = { 
  0: 'java'.1: 'script'.length: 2
} 
Array.prototype.push.call(arrayLike, 'jack'.'lily'); 
console.log(typeof arrayLike); // 'object'
console.log(arrayLike);
// {0: "java", 1: "script", 2: "jack", 3: "lily", length: 4}
Copy the code

Get the maximum and minimum value

With Apply, you can pass arrays directly as parameters without further expanding the array.

let arr = [13.6.10.11.16];
const max = Math.max.apply(Math, arr); 
const min = Math.min.apply(Math, arr);
console.log(max);  / / 16
console.log(min);  / / 6
Copy the code

inheritance

function Parent1(){
    this.name = 'parent1';
  }
  Parent1.prototype.getName = function () {
    return this.name;
  }

  // constructor inheritance
  function Child1(){
    Parent1.call(this);  // Parent1.apply(this) Parent1.bind(this)()
    this.type = 'child1'
  }
  // combinatorial inheritance
  Child1.prototype = new Parent1();
  Child1.prototype.constructor = Child1;

  let child = new Child1();
  console.log(child);  // No problem {name: "parent1", type: "child1"}
  console.log(child.getName());  / / complains
Copy the code

Method implementation

The new method

function _new(ctor, ... args) {
    if(typeofctor ! = ='function') {
      throw 'ctor must be a function';
    }
    let obj = new Object(a); obj.__proto__ =Object.create(ctor.prototype);
    let res = ctor.apply(obj,  [...args]);
    let isObject = typeof res === 'object'&& res ! = =null;
    let isFunction = typeof res === 'function';
    return isObject || isFunction ? res : obj;
};
Copy the code

Apply and Call methods

The basic principle of the two methods is similar, but the parameters are different

Function.prototype.call = function (context, ... args) {
  var context = context || window;
  context.fn = this;
  var result = eval('context.fn(... args)');
  delete context.fn
  return result;
}
Function.prototype.apply = function (context, args) {
  let context = context || window;
  context.fn = this;
  let result = eval('context.fn(... args)');
  delete context.fn
  return result;
}
Copy the code

The bind method

Bind is implemented in the same way as Apply, but at the end of the implementation, it returns the result. There is a big difference between Bind and Apply. Bind does not need to execute directly, so instead of using eval, you need to return the result by returning a function, and then executing the result. Get the desired execution.

Function.prototype.bind = function (context, ... args) {
    if (typeof this! = ="function") {
      throw new Error("this must be a function");
    }
    var self = this;
    var fbound = function () {
        self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
    }
    if(this.prototype) {
      fbound.prototype = Object.create(this.prototype);
    }
    return fbound;
}
Copy the code

The whole point of doing bind is that you need to return a function, so fbound needs to return,

But the properties on the prototype chain object cannot be lost in the return process. Create method to attach the this.prototype property to fbound’s prototype and return fbound.

This calls bind to receive the object of the function and then executes the received function to get the desired result