call, apply, bind的内部实现原理 https://www.cnblogs.com/renzhiwei2017/p/10364760.html
call, apply, bind都是改变函数执行的上下文,说的直白点就是改变了函数this的指向。不同的是:call和apply改变了函数的this,并且执行了该函数,而bind是改变了函数的this,并返回一个函数,但不执行该函数。
看下面的例子1:
var doThu = function(a, b) {
console.log(this)
console.log(this.name)
console.log([a, b])
}
var stu = {
name: 'xiaoming',
doThu: doThu,
}
stu.doThu(1, 2) // stu对象 xiaoming [1, 2]
doThu.call(stu, 1, 2) // stu对象 xiaoming [1, 2]
由此可见,在stu上添加一个属性doThu,再执行这个函数,就将doThu的this指向了stu。而call的作用就与此相当,只不过call为stu添加了doThu方法后,执行了doThu,然后再将doThu这个方法从stu中删除。
下面来看call函数的内部实现原理:
Function.prototype.call = function(thisArg, args) {
// this指向调用call的对象
if (typeof this !== 'function') { // 调用call的若不是函数则报错
throw new TypeError('Error')
}
thisArg = thisArg || window
thisArg.fn = this // 将调用call函数的对象添加到thisArg的属性中
const result = thisArg.fn(...[...arguments].slice(1)) // 执行该属性
delete thisArg.fn // 删除该属性
return result
}
apply的实现原理和call一样,只不过是传入的参数不同而已。下面只给出代码,不做解释:
Function.prototype.apply = function(thisArg, args) {
if (typeof this !== 'function') {
throw new TypeError('Error')
}
thisArg = thisArg || window
thisArg.fn = this
let result
if(args) {
result = thisArg.fn(...args)
} else {
result = thisArg.fn()
}
delete thisArg.fn
return result
}
bind的实现原理比call和apply要复杂一些,bind中需要考虑一些复杂的边界条件。bind后的函数会返回一个函数,而这个函数也可能被用来实例化:
Function.prototype.bind = function(thisArg) {
if(typeof this !== 'function'){
throw new TypeError(this + 'must be a function');
}
// 存储函数本身
const _this = this;
// 去除thisArg的其他参数 转成数组
const args = [...arguments].slice(1)
// 返回一个函数
const bound = function() {
// 可能返回了一个构造函数,我们可以 new F(),所以需要判断
if (this instanceof bound) {
return new _this(...args, ...arguments)
}
// apply修改this指向,把两个函数的参数合并传给thisArg函数,并执行thisArg函数,返回执行结果
return _this.apply(thisArg, args.concat(...arguments))
}
return bound
}
JavaWeb(一)Servlet中乱码解决与转发和重定向的区别
JavaWeb(一)Servlet中的request与response
JavaWeb(一)Servlet中的ServletConfig与ServletContext
JavaWeb(一)之细说Servlet
OOAD-设计模式(一)概述
异常处理升级版
MySQL优化原理
hadoop 有那些发行版本
centos7 安装搜狗输入法
- 最新文章
-
C# 实现WebSocket通信
C# Fleck的WebSocket使用
vue上如何用非表单元素绑定model的双向绑定
promise all的怎么处理异常
vue定义data的三种方式与区别
将文件复制到ftp服务器时发生错误,请检查是否有权限将文件放到该服务器上。 10
原生js获取元素的宽高
React 直接引入样式
非常规需求整理
MSSQL—行转列
- 热门文章
-
Mvc多级Views目录 asp.net mvc4 路由重写及 修改view 的寻找视图的规则
ASP.NET MVC4中@model使用多个类型实例的方法
ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步
FTP登录提示Can't open data connection for transfer of "/"
PHPExcel导出数据时字段超过26列出错Invalid cell coordinate [1
Linux下php安装Redis扩展
Linux 防火墙开放特定端口 (iptables)
通信——基于Xmpp协议实现的聊天室
JavaWeb(二)cookie与session的应用
开发问题(一)在windows和linux端口占用问题