Reference link: github.com/mqyqingfeng…

1. call

Pass any parameter and execute immediately

To call a function or method with a specified this value and specified parameter values:

var foo = { value : 1}
function bar(){
    console.log(this.value)
}
bar.call(foo)/ / 1
// Call changes the direction of this to foo;
// the bar function executes;
Copy the code

To realize the specified this value, the steps of simulation are divided into:

  • Set functions to properties of objects;
  • Execute the function;
  • Delete the function;
Function.prototype.call = function(context){
    // Get the function that calls call
    console.log(this)// bar(){ console.log( this.value ) }
    context.fn = this
    context.fn()
    delete context.fn
}
// Test it
var foo = { value : 1 }
function bar(){
    console.log(this.value)
}
bar.call(foo)// 1, equivalent to foo.bar()
Copy the code

Implements a number of specified parameter values:

  • Take the second to last Arguments from the Arguments object and place them in an array
Function.prototype.call = function(context){
    context.fn = this
    
    var args = [...arguments].slice(1) context.fn(... args)delete context.fn
}
// Test it
var foo = { value : 1 }
function bar(name,age){
    console.log(this.value)
    console.log(name)
    console.log(age)  
}
bar.call(foo,'zouyan'.'18')
/ / 1
// zouyan
/ / 18
Copy the code

Optimization:

  • The this parameter can be passed as null. If null, it refers to window.
  • A function can have a return value;
Function.prototype.call = function(context) {
  var context = context || window
  context.fn = this
  var args = [...arguments].slice(1)
  varresult = context.fn(... args)delete context.fn
  return result
}
// Test it
var value = 2
var foo ={ value : 1 }
function bar(name,age){
    console.log(this.value)
    return{
        value: this.value,
        name: name,
        age:age
    }
}
bar.call(null)/ / 2
bar.call(foo,'zouyan'.18)// {value:1,name:'zouyan',age:'18'}
Copy the code

2. apply

Pass in an array of parameters and execute immediately

Function.prototype.apply = function(context, arr) {
  var context = Object(context) || window
  context.fn = this

  var result
  if(! arr) { result = context.fn() }else {
    varargs = arr || [] result = context.fn(... args) }delete context.fn
  return result
}
// Test it
var value = 2
var foo ={ value : 1 }
function bar(name,age){
    console.log('value'.this.value)
    return{
        value: this.value,
        name: name,
        age:age
    }
}
bar.apply(null)
bar.apply(foo,['zouyan'.18])// {value:1,name:'zouyan',age:'18'}
Copy the code

3. bind

Pass in an argument and return a function that needs to be executed manually

  • The bind() method creates a new function;
  • The first argument passed to bind is this at runtime;
  • Other arguments passed as arguments to the function run time;
  • Two features: returns a function that can be passed in parameters;
// return function:
Function.prototype.bind = function(cxt){
    var self = this
    return function(){
        return self.apply(cxt)
    }
}
// Simulate parameter transfer
Function.prototype.bind = function(cxt){
    var self = this
    // Get bind from the second argument to the last argument
    var args = [].slice.call(arguments.1)
    return function(){
        // arguments refer to the arguments passed in by the function returned by bind
        var newArgs = args.concat([].slice.call(arguments))
        return self.apply(cxt, newArgs)
    }
}
Copy the code

A binding function can also use the new operator to create objects: this behavior is like treating the original function as a constructor. The supplied this value is ignored, and the arguments to the call are supplied to the mock function.

// Simulate the implementation constructor
Function.prototype.bind = function(cxt){
    var self = this
    var args = [].slice.call(arguments.1)
    var fNOP = function(){}
    var fBound = function(){
        var newArgs = args.concat([].slice.call(arguments))
        return self.apply(this instanceof fNOP ? this : cxt, newArgs)
    }
    fNOP.prototype = this.prototype
    fBound.prototype = new fNOP()
    return fBound
}
// Call the bind function
/ / compatible
Function.prototype.bind = function(cxt){
    if(typeof this! = ="function") {throw new Error("is not a function")}var self = this
    var args = [].slice.call(arguments.1)// Get the second argument to the last argument
    var fNOP = function(){}
    var fBound = function(){
        var newArgs = args.concat([].slice.call(arguments)) 
        return self.apply(this instanceof fNOP ? this : cxt, newArgs)
    }
    fNOP.prototype = this.prototype
    fBound.prototype = new fNOP()
    return fBound
}
Copy the code

4. new

  • Instances can access properties in constructors;
  • Instances can access properties in the constructor stereotype;

Implementation steps:

  • Create a new object obj: because new is a new object;
  • 2.obj._proto_The properties point to the constructor’s prototype: because the instance needs to access the properties on the prototype;
  • ③ Add new attributes to obj using apply, because obj has attributes in the constructor.
  • The obj: constructor may have a return value. The obj: constructor may have a return value.
// Simulate implementation of the new keyword
function objectFactory() {
    / / steps (1)
    var obj = new Object(),// Why is new used in mock new?
    //var obj = object. create(null),// error: TypeError
    Var obj = {},// Normal
    Create ({}),// Normal
    Create (Object. Prototype),// Normal
    
    / / step (2)
    // get the constructor, intercepting the first argument;
    // Shift modifies the array, so arguments are removed as an argument;
    Constructor = [].shift.call(arguments);/ / is equivalent to an Array. The prototype. The shift. The call (the arguments)
    obj.__proto__ = Constructor.prototype; 
    
    var ret = Constructor.apply(obj, arguments); / / steps (3)
    return typeof ret === 'object' ? ret||obj : obj; / / steps (4)
};
// constructor
function Otaku (name, age) {
    this.name = name;
    this.age = age;
    this.habit = 'Games';
}
Otaku.prototype.strength = 60;
Otaku.prototype.sayYourName = function () {
    console.log('I am ' + this.name);
}
// simulate creating an instance
var person = objectFactory(Otaku, 'Kevin'.'18')

console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) / / 60
person.sayYourName(); // I am Kevin
Copy the code