I. The principle of Call

Definition: To call a function with a specified value of this and one or more arguments given separately

Function. Call (thisArg, arg1, arg2…)

Principle analysis: in fact, the function that will be called as a property of the specified object, and then execute the property (method) of the specified object, and finally delete the property on the object, and return the result of execution. If no object is specified (e.g. null, undefined), the default is to point to the global object (window).

The specific implementation is as follows:

Function. The prototype. Call2 = Function (context) {context = context | | window context. The fn = this / / this is to perform the Function of var args =  [] for (var i = 1; i<arguments.length; i++) { args.push('arguments['+i+']') } var result = eval('context.fn('+args+')') delete context.fn return result }Copy the code

2, apply principle

Apply implements the same principle as above, except that the arguments passed in are arrays

Function.prototype.apply2 = function (context, arr) { context = context || window context.fn = this var result if (! arr) { result = context.fn() } else { var args = [] for (var i = 0; i < arr.length; i++) { args.push('arguments['+i+']') } result = eval('context.fn('+args+')') } delete context.fn return result }Copy the code

3. Bind principle

Definition: the bind method creates a new function. When bind is called, this points to the first argument of the new function, and the rest of the arguments are used as arguments to the new function

ThisArg [, arg1[, arg2[,…]]])

Principle analysis:

  1. The bind method returns a new function
  2. When the new function executes, its this refers to the first argument to bind
  3. When a new function is executed, all arguments except the first argument of bind are combined with the arguments passed in the call to the new function

The initial realization is as follows:

Function.prototype.bind2 = function (context) {
  var fn = this
  var arg = Array.prototype.slice.call(arguments, 1)
  var fbound = function () {
    var bindArg = Array.prototype.slice.call(arguments)
    fn.apply(context, arg.concat(bindArg))
  }
  return fbound
}
Copy the code

Another feature of bind is that if the function (fbound) returned by bind is used as a constructor, then the “this” inside the function (fbound) refers to its instance, ignoring the context passed by bind

Here’s an example:

var value = 2 var foo = { value: 1 } function bar(name, age) { this.habit = 'shopping'; Obj console.log(this.value); console.log(name); console.log(age); } bar.prototype.friend = 'kevin'; var bindFoo = bar.bind(foo, 'daisy') var obj = new bindFoo('18'); console.log(obj.habit); console.log(obj.friend); // output: // undefined // Daisy // 18 // shopping // KevinCopy the code

The final implementation is as follows:

Function.prototype.bind2 = function (context) { var self = this var args = Array.prototype.slice.call(arguments, Var fNOP = function () {} var fbound = function () {this is an instance of fbound, While self refers to the binding function (constructor) // as a normal function, this refers to the window, Self directed binding function var bindArg = Array. The prototype. Slice. The call (the arguments) return self. Apply (this instanceof self? this : context, args.concat(bindArg)) } fNOP.prototype = self.prototype; Fbound.prototype = new fNOP() // The reason for not writing this is that if you change fbound.prototype, // fbound.prototype = self.prototype; // fbound.prototype = self.prototype; return fbound }Copy the code

4. New Principle

Characteristic analysis:

  1. New XXX() returns a new Object. (var obj = new Object())
  2. (var result = xxx. apply(obj)) (obj has the properties in the constructor)
  3. The new object can access the stereotype property in the constructor (that is, obj._proto_= XXX. Prototype?)
  4. If the constructor returns an object, then the result of new is that object.

As an example, check # 4

function Person () {
  this.name = 'zbq'
  this.age = 18
  return {
    name: 'lisi',
    age: 12
  }
}

var obj = new Person()
console.log(obj)
// { name: 'lisi', age: 12 }
Copy the code

The specific implementation is as follows:

Function objectFactory() {var Constructor = [].shift.call(arguments) var obj = new Object() obj.__proto__ = Constructor.prototype var result = Constructor.apply(obj, arguments) return typeof result === 'object' ? (the result | | obj) : obj / / because the typeof null = > 'object', if the result is null, it returns the obj}Copy the code

Five, the reference

  • Juejin. Cn/post / 684490…
  • Juejin. Cn/post / 684490…
  • Juejin. Cn/post / 684490…