记录call、apply、bind的源码
记录一下call、apply、bind的源码,然后从根本上明白其用法。
都知道call、apply与bind的用法,call(this,...arguments)、apply(this,[arguments])、var fn = bind(this, ...arguments);fn(...newarguments);
call和apply都是立即执行,只是传参数形式不一样,call参数一字排开,apply参数是数组,bind绑定之后返回一个新函数但是并不立即执行,需要额外调用的时候才执行,并且,绑定的时候可以额外传参数,执行的时候也可以额外传参数。
call和apply执行的本质是,往要绑定的context对象下添加该函数,然后执行,最后将属性删除。当context值为null,或者undefined时,非严格模式下,它将替换为window或者global全局变量。
Function.prototype.call = function (context) {var context = context || window;context.fn = this;var args = [];for(var i = 1, len = arguments.length; i < len; i++) {args.push('arguments[' + i + ']');}var result = eval('context.fn(' + args +')');delete context.fnreturn result; }
Function.prototype.apply = function (context, arr) {var context = Object(context) || window;context.fn = this;var result;if (!arr) {result = context.fn();}else {var args = [];for (var i = 0, len = arr.length; i < len; i++) {args.push('arr[' + i + ']');}result = eval('context.fn(' + args + ')')}delete context.fnreturn result; }
bind因为不会立刻执行,而是返回一个函数,一般情况下,该函数执行时的this指向绑定的对象。而麻烦的是JS中该函数还可以通过new来实例化,而实例化之后的this要指向新创建的对象,不能再跟着绑定的对象走了,所以该函数内部对this进行了额外处理,看它是否是通过new创建的实例,如果是通过new创建的实例,this对象指向新创建的new对象实例。
if (!Function.prototype.bind) {Function.prototype.bind = function (oThis) {if (typeof this !== "function") {throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");}var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () {},fBound = function () {return fToBind.apply(this instanceof fNOP? this: oThis || this,aArgs.concat(Array.prototype.slice.call(arguments)));};fNOP.prototype = this.prototype;fBound.prototype = new fNOP();return fBound;}; }
转载于:https://www.cnblogs.com/liujiekun/p/11295183.html
记录call、apply、bind的源码相关推荐
- 超好看的情侣纪念日记录单页HTML自适应源码
正文: 超好看的情侣纪念日记录单页HTML自适应源码,这程序源码的UI非常好看,具体演示可以看上方的封面图. 下方是作者的原话: 使用方法: 大部分内容都在index.html里面进行修改 " ...
- 编译linux源码报错,记录一次Linux内核源码编译实验
记录一次Linux内核源码编译实验 文章目录 记录一次Linux内核源码编译实验 0. 实验环境 1. 选择.下载内核源码 2. 安装必要的依赖软件以及性能要求 3. 解压.配置和编译内核源码 3.1 ...
- 自己写了好久的SSM个人博客。。。记录下,并分享 源码----(SpringBoot+Thymeleaf+layui+mybatis)
预览图 预览地址:www.dreamylost.cn 后台 手机 ipad 大三工作室练手项目.(IP暂时没有找到很好的免费办法,学校教育网,都是一个nginx地址,最好用手机测试ip相关功能,富文 ...
- 微软文本转语音实测记录附php/go调用源码
接口地址 地址:http://www.mysqlschool.cn/SpeekText/index.php 提交方式:post/get 推荐post 例子:http://www.mysqlschool ...
- WebRTC应用问题记录(附项目demo源码)
为什么icecandidate事件不触发? 必须在setLocalDescription和setRemoteDescription之后,该事件才会触发 为什么手机可以和手机通话,电脑可以和电脑通话,但 ...
- r8169驱动源码阅读记录
r8169驱动源码阅读记录 初始化 发包 收包 源码地址:linux-4.19.90\drivers\net\ethernet\realtek\r8169.c 源码阅读环境:Windows 搭建 op ...
- Spark-Core源码学习记录 3 SparkContext、SchedulerBackend、TaskScheduler初始化及应用的注册流程
Spark-Core源码学习记录 该系列作为Spark源码回顾学习的记录,旨在捋清Spark分发程序运行的机制和流程,对部分关键源码进行追踪,争取做到知其所以然,对枝节部分源码仅进行文字说明,不深入下 ...
- call apply bind 深入了解
不知其理,何以谈用 众所周知 call.apply.bind 的作用都是'改变'作用域,但是网上对这这'改变'说得含糊其辞,并未做详细说明,'改变'是直接替换作用域?谁替换谁?怎么产生效果?这些问题如 ...
- nodeJS之eventproxy源码解读
1.源码缩影 !(function (name, definition) { var hasDefine = typeof define === 'function', //检查上下文环境是否为AMD ...
最新文章
- 无密码进去mysql_技术分享 | 安全地无密码登录 MySQL
- 如何找回无法运行此项请求机械硬盘的文件
- 远程桌面连接出现身份验证错误。 要求的函数不受支持,这可能是由于 CredSSP 加密 Oracle 修正。...
- iPhone 12“概念视频”曝光:被恶搞的太惨了
- ant Design表单验证笔记
- 设计模式(二):难忘一次分享盛宴
- VertrigoServ 2.21配置phpmyadmin
- Bailian4106 出现两次的字符-Characters Appearing twice【计数统计】
- Echarts数据可视化全解注释
- Java:Spi 小实战
- 主流数据库对比,主流数据库性能、选型对比
- 【网易云课堂】产品运营学习
- linux版本的pdf软件,3款可以注释标注的Linux版pdf阅读器评测
- 计算机屏幕显示不能全屏,电脑屏幕小软件显示不全
- IT十年人生过客-十八-路过机遇
- (整理)Ruby的基础知识
- android开发分辨率,安卓APP设计规范之1080*1920设计稿对应开发尺寸
- ajax timeout 内存溢出,setInterval 和 setTimeout会产生内存溢出
- 三中新教学楼信息系统集成方案
- openstack部署过程4
热门文章
- 备份集中的数据库备份与现有的 '***' 数据库不同 RESTORE DATABASEnbs
- 音视频即时通讯的介绍与前景
- Pair Programming 1 (Casual Game) 曹竹 杨牧 贪吃蛇游戏扩展 Blog Report
- Android异步下载网络图片(其一:Handler)
- Android PullToRefresh (ListView GridView 下拉刷新) 使用详解
- gin自定义路由日志的格式
- mybaits四-3:获取保存数据的id
- 设计模式:设计模式七大原则
- WebApi数据验证——编写自定义数据注解(Data Annotations)
- max分发-(网络系统克隆)