当前位置:网站首页>有趣且重要的JS知识合集(13)call/apply/bind 源码级实现
有趣且重要的JS知识合集(13)call/apply/bind 源码级实现
2022-07-13 16:35:00 【林大大哟】
1、call 的源码实现
Function.prototype._call = function(){
let context = [].shift.call(arguments) // 类数组对象转数组,删除并返回第一个参数 this
let args = arguments // 剩余参数
context = context || window
context._this = this
context._this(...args) // 将类数组对象展开
delete context._this
}2、apply的源码实现
Function.prototype._apply = function(){
let context = [].shift.call(arguments) // 类数组对象转数组,删除并返回第一个参数 this
let args = [].slice.call(...arguments) // 类数组对象转数组(剩余参数)
context = context || window
context._this = this
context._this(...args)
delete context._this
}调用方式
3、bind的源码实现
Function.prototype._bind = function(){
let _this= this //原函数
let context = [].shift.call(arguments) // 类数组对象转数组,删除并返回第一个参数 this
let args = [].slice.call(arguments) // 类数组对象转数组(剩余参数)
return function(){
_this.apply(context, args)
}
}4、调用方式及原理详解
var person = {
name: "林大大哟",
gender: "男",
work: function(enterprise, job) {
console.log(this.name + " , " + this.gender + " , 在" + enterprise + "做" + job);
}
}
// call 方式
person.work._call(person, '某某公司','前端开发'); // 林大大哟 , 男 ,在某某公司做前端开发
// apply 方式
person.work._apply(person, ['某某公司','前端开发']); // 林大大哟 , 男 ,在某某公司做前端开发
// bind 方式
person.work._bind(person)('某某公司','前端开发'); // 林大大哟 , 男 ,在某某公司做前端开发
person.work._bind(person, '某某公司','前端开发')(); // 林大大哟 , 男 ,在某某公司做前端开发call和apply原理略解
call和apply都是第一参数为调用对象,唯一不同就是后续参数不同,apply为数组,call为任意参数,所以再重写这俩原型时,其实会发现,我并没有显示定义形参,而是通过arguments来获取参数(arguments为类数组对象,和直接数组不同,想要了解的可以自行搜索)。
下面两行是出现在喔代码里最频繁的,如何理解呢,其实就跟 Array.prototype.shift / slice含义一致,将类数组对象转换成数组,细心点同学会发现,context我们三个重写函数都是一致的,但是args不一致,这是为什么呢?因为最后在调用时我们需要通过拓展符来讲参数展开(那么为什么要展开? 因为上面例子中的work函数形参是分开定义的喔~)所以意味着在最后调用时,必须将所有数组给展开,_apply 函数因为传实参时是传入的数组,然后经过 [].slice.call, 又封装了一层数组,就是二维数组了,所以[].slice.call(...arguments) 这里使用了一次拓展符,然后在调用时又使用了一次拓展符。
let context = [].shift.call(arguments) // 类数组对象转数组,删除并返回第一个参数 this
let args = [].slice.call(...arguments) // apply 重写 类数组对象转数组(剩余参数)
let args = arguments // call 重写 类数组对象转数组(剩余参数)bind原理略解
bind其实可以看作call和apply的升阶版,因为bind直接返回当前的构造函数,所以我们在最外层调用时,需要再加一个括号才能执行bind函数,那么这部分有同学就会觉得,那这就是闭包啊,bingo,是滴,其实就是闭包的应用,那么既然涉及到闭包,肯定传参方式就不止一种了
person.work._bind(person)('某某公司','前端开发');
person.work._bind(person, '某某公司','前端开发')(); 既可以将自定义参数,类似于call方式调用,也可以当作立即执行函数方式来调用
边栏推荐
- Browser executes JS process
- Very practical SQL optimization scheme
- 从零实现一个日志框架
- Xilinx Vitis
- World premiere! The benchmark of 18 years of hot sales will be replaced, and the fuel hybrid will be optional. Seven new seats will be added, and the safety will be upgraded. Just wait!
- 深入浏览器的渲染原理
- Compilation principle experiment IV LR (0) analysis method (automatic generation of Lr0 analysis table) complete code
- Some interview questions encountered recently -- WPF, C #, database
- Pagebean introduction
- Multiple table connections
猜你喜欢

ES6:箭头函数用法

Optimisation SQL très pratique

The ideal L9 is equipped with flagship safety configuration, which makes the whole family travel safer and more convenient

进制转换

【北京林业大学】考研初试复试资料分享

Heavyweight new | shangsilicon Valley C4d 3D design practical tutorial release

JS 之 彻底搞懂this指向

ANR的学习

Wechat applet 1- applet foundation, development tool installation and use

开拓“一带一路”新机遇 湄潭茶叶创新走向世界
随机推荐
微信小程序1-小程序基础,开发工具安装使用
主席树复习
手机号码校验正则表达式
Wechat applet 4 - applet API
JDBC的详细讲解和注意事项
Some interview questions encountered recently -- WPF, C #, database
Embedded system final review outline
ANR的学习
Codeforces Round #805 (Div. 3) - E, F, G
Interview question 08.04 Power set
Wechat applet 5 real machine test
Remember to be quick in investment
JSP realizes fuzzy query with drop-down box selection and search box
[200 opencv routines] 228 Extendlbp improved operator of feature description
富民县科协积极开展安全食用野生菌应急科普宣传工作
Use of listview and recyclerview
互联网对内核模块的加载之道
rem适配方案
sql2008强制重设了sa的密码重启后sql登录成功。但是访问服务器时提示sa登录失败。
[paper notes] deep reinforcement learning for robotic pushing and picking in cluttered environment