当前位置:网站首页>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;
}
边栏推荐
- 对话PPIO联合创始人王闻宇:整合边缘算力资源,开拓更多音视频服务场景
- Decrypt gd32 MCU product family, how to choose the development board?
- [play RT thread] RT thread Studio - key control motor forward and reverse rotation, buzzer
- Static routing assignment of network reachable and telent connections
- Sign up now | oar hacker marathon phase III midsummer debut, waiting for you to challenge
- ps链接图层的使用方法和快捷键,ps图层链接怎么做的
- Visual studio 2019 (localdb) \mssqllocaldb SQL Server 2014 database version is 852 and cannot be opened. This server supports version 782 and earlier
- wallys/Qualcomm IPQ8072A networking SBC supports dual 10GbE, WiFi 6
- Niuke website
- Financial data acquisition (III) when a crawler encounters a web page that needs to scroll with the mouse wheel to refresh the data (nanny level tutorial)
猜你喜欢
H3C HCl MPLS layer 2 dedicated line experiment
leetcode刷题:二叉树22(二叉搜索树的最小绝对差)
Processing strategy of message queue message loss and repeated message sending
The left-hand side of an assignment expression may not be an optional property access. ts(2779)
wallys/Qualcomm IPQ8072A networking SBC supports dual 10GbE, WiFi 6
Inverted index of ES underlying principle
leetcode刷题:二叉树23(二叉搜索树中的众数)
(待会删)yyds,付费搞来的学术资源,请低调使用!
"Series after reading" my God! It's so simple to understand throttling and anti shake~
数据库系统原理与应用教程(011)—— 关系数据库
随机推荐
The left-hand side of an assignment expression may not be an optional property access.ts(2779)
30. Feed shot named entity recognition with self describing networks reading notes
College entrance examination composition, high-frequency mention of science and Technology
Vxlan 静态集中网关
千人规模互联网公司研发效能成功之路
sql-lab (54-65)
Introduction and application of smoothstep in unity: optimization of dissolution effect
SQL blind injection (WEB penetration)
即刻报名|飞桨黑客马拉松第三期盛夏登场,等你挑战
Simple network configuration for equipment management
2022危险化学品生产单位安全生产管理人员考题及在线模拟考试
【玩转 RT-Thread】 RT-Thread Studio —— 按键控制电机正反转、蜂鸣器
Typescript interface inheritance
ps链接图层的使用方法和快捷键,ps图层链接怎么做的
Preorder, inorder and postorder traversal of binary tree
Sonar:cognitive complexity
Minimalist movie website
【统计学习方法】学习笔记——第四章:朴素贝叶斯法
How to use PS link layer and shortcut keys, and how to do PS layer link
Experiment with a web server that configures its own content