当前位置:网站首页>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;
}
边栏推荐
- 【统计学习方法】学习笔记——第五章:决策树
- Introduction and application of smoothstep in unity: optimization of dissolution effect
- gcc 编译报错
- About sqli lab less-15 using or instead of and parsing
- 通讯协议设计与实现
- [pytorch practice] image description -- let neural network read pictures and tell stories
- 金融数据获取(三)当爬虫遇上要鼠标滚轮滚动才会刷新数据的网页(保姆级教程)
- NGUI-UILabel
- 【统计学习方法】学习笔记——支持向量机(上)
- 编译 libssl 报错
猜你喜欢
About web content security policy directive some test cases specified through meta elements
即刻报名|飞桨黑客马拉松第三期盛夏登场,等你挑战
SQL lab 26~31 summary (subsequent continuous update) (including parameter pollution explanation)
About sqli lab less-15 using or instead of and parsing
[deep learning] image multi label classification task, Baidu paddleclas
Configure an encrypted web server
111. Network security penetration test - [privilege escalation 9] - [windows 2008 R2 kernel overflow privilege escalation]
SQL Lab (41~45) (continuous update later)
跨域问题解决方案
Ctfhub -web SSRF summary (excluding fastcgi and redI) super detailed
随机推荐
Is it safe to open Huatai's account in kainiu in 2022?
2022危险化学品生产单位安全生产管理人员考题及在线模拟考试
免备案服务器会影响网站排名和权重吗?
VSCode的学习使用
爱可可AI前沿推介(7.7)
Decrypt gd32 MCU product family, how to choose the development board?
College entrance examination composition, high-frequency mention of science and Technology
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
IPv6 experiment
idea 2021中文乱码
@What happens if bean and @component are used on the same class?
Static routing assignment of network reachable and telent connections
sql-lab (54-65)
H3C HCl MPLS layer 2 dedicated line experiment
leetcode刷题:二叉树27(删除二叉搜索树中的节点)
数据库系统原理与应用教程(007)—— 数据库相关概念
SQL blind injection (WEB penetration)
[deep learning] image multi label classification task, Baidu paddleclas