当前位置:网站首页>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); // undefined
In 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;
}
边栏推荐
- Idea 2021 Chinese garbled code
- 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
- 【玩转 RT-Thread】 RT-Thread Studio —— 按键控制电机正反转、蜂鸣器
- About sqli lab less-15 using or instead of and parsing
- Configure an encrypted web server
- 2022广东省安全员A证第三批(主要负责人)考试练习题及模拟考试
- Epp+dis learning road (2) -- blink! twinkle!
- 关于 Web Content-Security-Policy Directive 通过 meta 元素指定的一些测试用例
- [deep learning] image multi label classification task, Baidu paddleclas
- [statistical learning methods] learning notes - improvement methods
猜你喜欢
MPLS experiment
Dialogue with Wang Wenyu, co-founder of ppio: integrate edge computing resources and explore more audio and video service scenarios
Solve server returns invalid timezone Go to ‘Advanced’ tab and set ‘serverTimezone’ property manually
An error occurred when vscade tried to create a file in the target directory: access denied [resolved]
Completion report of communication software development and Application
leetcode刷题:二叉树27(删除二叉搜索树中的节点)
消息队列消息丢失和消息重复发送的处理策略
[deep learning] image multi label classification task, Baidu paddleclas
解密GD32 MCU产品家族,开发板该怎么选?
Cookie
随机推荐
2022A特种设备相关管理(锅炉压力容器压力管道)模拟考试题库模拟考试平台操作
leetcode刷题:二叉树27(删除二叉搜索树中的节点)
Solutions to cross domain problems
Customize the web service configuration file
@What happens if bean and @component are used on the same class?
Niuke website
【统计学习方法】学习笔记——第五章:决策树
【深度学习】图像多标签分类任务,百度PaddleClas
EPP+DIS学习之路(2)——Blink!闪烁!
Completion report of communication software development and Application
Experiment with a web server that configures its own content
2022聚合工艺考试题模拟考试题库及在线模拟考试
Vxlan static centralized gateway
通讯协议设计与实现
DOM parsing XML error: content is not allowed in Prolog
消息队列消息丢失和消息重复发送的处理策略
Inverted index of ES underlying principle
SQL blind injection (WEB penetration)
The hoisting of the upper cylinder of the steel containment of the world's first reactor "linglong-1" reactor building was successful
Xiaohongshu microservice framework and governance and other cloud native business architecture evolution cases