当前位置:网站首页>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;
}
边栏推荐
- @What happens if bean and @component are used on the same class?
- H3C HCl MPLS layer 2 dedicated line experiment
- Simple network configuration for equipment management
- Learning and using vscode
- Attack and defense world - PWN learning notes
- BGP actual network configuration
- OSPF exercise Report
- Hi3516 full system type burning tutorial
- leetcode刷题:二叉树26(二叉搜索树中的插入操作)
- leetcode刷题:二叉树19(合并二叉树)
猜你喜欢

Ctfhub -web SSRF summary (excluding fastcgi and redI) super detailed

AirServer自动接收多画面投屏或者跨设备投屏

千人规模互联网公司研发效能成功之路

About sqli lab less-15 using or instead of and parsing

Simple network configuration for equipment management

leetcode刷题:二叉树25(二叉搜索树的最近公共祖先)

即刻报名|飞桨黑客马拉松第三期盛夏登场,等你挑战

Xiaohongshu microservice framework and governance and other cloud native business architecture evolution cases

Static vxlan configuration

Minimalist movie website
随机推荐
Tutorial on principles and applications of database system (007) -- related concepts of database
Tutorial on principles and applications of database system (010) -- exercises of conceptual model and data model
What are the technical differences in source code anti disclosure
Pule frog small 5D movie equipment | 5D movie dynamic movie experience hall | VR scenic area cinema equipment
SQL Lab (36~40) includes stack injection, MySQL_ real_ escape_ The difference between string and addslashes (continuous update after)
Vxlan static centralized gateway
Typescript interface inheritance
ps链接图层的使用方法和快捷键,ps图层链接怎么做的
Sort out the garbage collection of JVM, and don't involve high-quality things such as performance tuning for the time being
Sonar:cognitive complexity
NGUI-UILabel
wallys/Qualcomm IPQ8072A networking SBC supports dual 10GbE, WiFi 6
On valuation model (II): PE index II - PE band
Learning and using vscode
<No. 9> 1805. Number of different integers in the string (simple)
SQL Lab (41~45) (continuous update later)
2022危险化学品生产单位安全生产管理人员考题及在线模拟考试
数据库系统原理与应用教程(008)—— 数据库相关概念练习题
Simple network configuration for equipment management
SQL blind injection (WEB penetration)