call
function
- Features:
- 1) We can change the this reference of our current function
- 2) It also makes the current function execute
Function.prototype.call = function (context) {
if (typeof this! = ='function') {
throw new TypeError(`The ${this} is not a function`)
}
context = Object(context) || window;
context.fn = this;
let args = [];
for (let i = 1; i < arguments.length; i++) {
args.push('arguments['+i+'] ');
}
let r = eval('context.fn('+args+') ');
delete context.fn;
return r;
}
Copy the code
The title self-test
function fn1() {
console.log(this.arguments);
console.log(1);
}
function fn2() {
console.log(this.arguments);
console.log(2);
}
fn1.call(fn2,1.2); / / fn2 [1, 2] 1
fn1.call.call.call.call.call(fn2,1.2); // {number:1} [2] 2
Copy the code
- Thinking analytical
Fn1. Call (fn2, 1, 2)
- 1)
call
Perform incomingfn2
.1
.2
Three parameters - 2)
call
Function of the internalcontext = Object(fn2) = fn2
- 3)
fn2.fn = fn1
- 4)
Args = [' the arguments [1] 'and' the arguments [2] '] = [1, 2]
- 5)
The eval (' context. Fn (' + args + ') ') = fn2. Fn (1, 2) = fn2. Fn1 (1, 2)
- 1)
Fn1. Call. The call. The call. The call. The call (fn2, 1, 2)
- 1)
call
Perform incomingfn2
.1
.2
Three parameters - 2)
call
Function of the internalcontext = Object(fn2) = fn2
- 3)
fn2.fn = call
- 4)
Args = [' the arguments [1] 'and the arguments [2]] = [1, 2]
- 5)
The eval (' context. Fn (' + args + ') ') = fn2. Fn (1, 2) = fn2. Call (1, 2)
- 6)
call
Perform incoming1
.2
Two parameters - 7)
call
Function of the internalcontext = Object(1) = Number{1}
- 8)
Number{1}.fn = fn2
- 9)
args=['arguments[1]']=[1]
- 10)
eval('context.fn('+args+')') = Number{1}.fn(2) = Number{1}.fn2(2)
- Note: Multiple calls
call
“Is actuallycall
It is called internally again at execution timecall
, called twice in total
- 1)
apply
function
- Features:
- 1) We can change the this reference of our current function
- 2) It also makes the current function execute
Function.prototype.apply = function (context,args) {
if (typeof this! = ='function') {
throw new TypeError(`The ${this} is not a function`)
}
context = Object(context) || window;
context.fn = this;
if(! args){return context.fn();
}
let r = eval('context.fn('+args+') ');
delete context.fn;
return r;
}
Copy the code
new
The operator
- The characteristics of
- Freshmen become objects
- Link to the prototype
- The binding
this
- Return an object
/* * Basic use */
function Animal(type) {
this.type = type ;
}
Animal.prototype.say = function () {
console.log('say');
}
let tiger = new Animal('tiger');
console.log(tiger);
--------------------------------------------------------
The /* * method implements */
function mockNew(){
let Constructor = [].shift.call(arguments);
let obj = {}; // Freshmen become objects
obj.__proto__ = Constructor.prototype; // Link to the prototype
let r = Constructor.apply(obj,arguments) / / bind ` this `
return r instance Object ? r : obj; // Return an object
}
let tiger = mockNew(Animal,'tiger');
console.log(tiger);
Copy the code
bind
function
- The characteristics of
- The binding
this
Point to the - Return a bound function (higher-order function principle)
- If the bound function is
new
To execute the current functionthis
Is the current instance new
The result is a prototype of the original class
- The binding
Function.prototype.bind = function (context) {
if (typeof this! = ='function') {
throw new TypeError(`The ${this} is not a function`)}let that = this;
let bindArgs = Array.prototype.slice.call(arguments.1);
function Fn() {};function bindFn() {
let args = Array.prototype.slice.call(arguments);
/* * Bind 'this' to * if the bound function is executed by' new ', the 'this' of the current function is the current instance */
that.apply(this instanceof bindFn ? this : context, bindArgs.concat(args));
}
/* 'new' results can find the original class prototype */
Fn.prototype = that.prototype;
bindFn.prototype = new Fn();
/* Returns a bound function */
return bindFn;
}
Copy the code