当前位置:网站首页>Simple implementation of call, bind and apply
Simple implementation of call, bind and apply
2022-07-07 12:35:00 【Xiaoding Chong duck!】
Preface :
These three are all functions api, Used to change this The direction of , Enable an object to call another method that does not belong to it , The core idea is through Change the this Point to , Borrow others' methods .
One 、call
adopt Object call implicit binding this Method implementation of , Because execution obj1.getName.myCall(obj), be myCall Medium this It means pointing. obj1.getName Of , Then add the method to the object you want to use .
Function.prototype.myCall = function (context = window, ...args) {
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
// here this Is refers to [Function: getName], To add methods to context On
context.$fn = this;
// Call the function implicitly
const result = context.$fn(...args);
// Remove added properties
delete context.$fn;
// Returns the return value of a function call
return result;
}But hang the function on the incoming object (context) in , In order to avoid the problem of duplicate name coverage , have access to symbol rewrite , as follows :
Function.prototype.myCall = function (context = window, ...args) {
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
// here this Is refers to [Function: getName], To add methods to context On
let fn = Symbol('call');
context[fn] = this;
// Call the function implicitly
const result = context[fn](...args);
// Remove added properties
delete context[fn];
// Returns the return value of a function call
return result;
}verification :
let obj = {
name: 'obj'
};
let obj1 = {
name: 'obj1',
getName: function (age, hobby) {
return this.name + ' This year, ' + age + ' year , like ' + hobby;
}
};
console.log(obj1.getName.myCall(obj, 12, ' Sing a song ')); // obj This year, 12 year , Like singing
Two 、apply
apply The implementation principle is the same , Only the format of parameter transmission is different , Just put the args Just change it
Function.prototype.myApply = function (context = window, args = []) {
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
// here this Is refers to [Function: getName], To add methods to context On
context.$fn = this;
// Call the function implicitly
const result = context.$fn(...args);
// Remove added properties
delete context.$fn;
// Returns the return value of a function call
return result;
}verification :
let obj = {
name: 'obj'
};
let obj1 = {
name: 'obj1',
getName: function (age, hobby) {
return this.name + ' This year, ' + age + ' year , like ' + hobby;
}
};
console.log(obj1.getName.myApply(obj, [12, ' Sing a song '])); // obj This year, 12 year , Like singing 3、 ... and 、bind
And call and apply The difference is ,bind() Method creates a new function , stay bind() When called , Of this new function this Is specified as bind The first parameter of , The remaining parameters will be specified as parameters of the new function , For calling .
characteristic :
- Returns a new function
- bind As the first parameter of the new function this
- All other parameters (bind And the second call ) As a parameter of the new function
The first one is :
Unsupported use new Call the newly created constructor
Function.prototype.myBind = function () {
let fn = this;
let asThis = arguments[0], args = [...arguments].slice(1);
if (typeof fn !== 'function') {
throw new TypeError('Function.prototype.bind - ' + 'what is trying to be bound is not callable');
}
return function () {
let args2 = [...arguments];
let fnArgs = args.concat(args2);
return fn.apply(asThis, fnArgs);
}
}verification :
let person = {
name: ' Xiaohong '
}
function Person(value) {
return this.name + ' like ' + Array.prototype.slice.call(arguments);
}
let demo = Person.myBind(person, ' Sing a song ');
console.log(demo(' dance ')); // Xiao Hong likes singing , dance But this is the case , If you use new Call the newly created constructor , There will be this Point to the problem of change , as follows :
let person = {
name: ' Xiaohong '
}
function Person(value) {
return this.name + ' like ' + Array.prototype.slice.call(arguments);
}
let Demo = Person.myBind(person, ' Sing a song ');
let demo = new Demo(' dance ');
console.log(demo.name); // undefinedIn fact, at this time, we hope demo.name Or print Xiaohong , But by new after ,this It points to demo example , therefore demo.name Namely undefined
So there is a second way to write , The following writing method supports the use of new Call the newly created constructor :
Function.prototype.myBind = function () {
let fn = this;
// console.log(this);
let asThis = arguments[0], args = Array.prototype.slice.call(arguments, 1);
if (typeof fn !== 'function') {
throw new TypeError('Function.prototype.bind - ' + 'what is trying to be bound is not callable');
}
let resultFn = function () {
let args2 = Array.prototype.slice.call(arguments);
let fnArgs = args.concat(args2);
let that = this instanceof resultFn ? this : asThis;
return fn.apply(that, fnArgs);
};
// Enable the instance to inherit the prototype of the binding function
function tmp() {};
tmp.prototype = fn.prototype;
resultFn.prototype = new tmp();
return resultFn;
}
边栏推荐
- SQL head injection -- injection principle and essence
- Utiliser la pile pour convertir le binaire en décimal
- VSCode的学习使用
- Unity map auto match material tool map auto add to shader tool shader match map tool map made by substance painter auto match shader tool
- Epp+dis learning road (2) -- blink! twinkle!
- wallys/Qualcomm IPQ8072A networking SBC supports dual 10GbE, WiFi 6
- The IDM server response shows that you do not have permission to download the solution tutorial
- The left-hand side of an assignment expression may not be an optional property access.ts(2779)
- SQL Lab (36~40) includes stack injection, MySQL_ real_ escape_ The difference between string and addslashes (continuous update after)
- "Series after reading" my God! It's so simple to understand throttling and anti shake~
猜你喜欢

Multi row and multi column flex layout

idea 2021中文乱码

leetcode刷题:二叉树26(二叉搜索树中的插入操作)

Vxlan 静态集中网关

College entrance examination composition, high-frequency mention of science and Technology

SQL Lab (41~45) (continuous update later)

Idea 2021 Chinese garbled code

【深度学习】图像多标签分类任务,百度PaddleClas

Sign up now | oar hacker marathon phase III midsummer debut, waiting for you to challenge

Pule frog small 5D movie equipment | 5D movie dynamic movie experience hall | VR scenic area cinema equipment
随机推荐
Pule frog small 5D movie equipment | 5D movie dynamic movie experience hall | VR scenic area cinema equipment
【统计学习方法】学习笔记——逻辑斯谛回归和最大熵模型
NGUI-UILabel
【PyTorch实战】用RNN写诗
Using stack to convert binary to decimal
What is an esp/msr partition and how to create an esp/msr partition
Solutions to cross domain problems
免备案服务器会影响网站排名和权重吗?
In the small skin panel, use CMD to enter the MySQL command, including the MySQL error unknown variable 'secure_ file_ Priv 'solution (super detailed)
EPP+DIS学习之路(1)——Hello world!
利用栈来实现二进制转化为十进制
SQL head injection -- injection principle and essence
【深度学习】图像多标签分类任务,百度PaddleClas
Attack and defense world ----- summary of web knowledge points
利用棧來實現二進制轉化為十進制
【PyTorch实战】图像描述——让神经网络看图讲故事
SQL lab 21~25 summary (subsequent continuous update) (including secondary injection explanation)
Aike AI frontier promotion (7.7)
密码学系列之:在线证书状态协议OCSP详解
[Q&A]AttributeError: module ‘signal‘ has no attribute ‘SIGALRM‘