Function.apply.bind()与Function.apply.bind()
1.Function.apply.bind(…)
我在学习promise部分的时候遇到了这样的代码:
Promise.resolve([10,20]).then(Function.apply.bind(function(x, y){
console.log(x, y);
}, null)); // 10,20
看到这里我已经蒙圈了,Function.apply.bind(…)是个什么操作?可能很多人和我一样之前只接触过Function.bind.apply(…)。
于是查了一下文档,大致明白了其中的含义。先撇开Promise不谈,直接来看Function.apply.bind(…):
var sum = function(x, y) {
console.log(x, y);
}
var foo = Function.apply.bind(sum, null);
foo([10, 20]); // 10, 20
这里我们有一个函数sum,通过Function.apply.bind(sum, null)我们创建了一个新的函数foo(…)。
我们一步步分析Function.apply.bind(sum, null)这段代码。
sum.apply(null, [10, 20])这句代码将第一个参数置为null,第二个参数是一个数组,用于拆开后作为sum的最终参数。
熟悉sum.apply(…)方法的朋友一定知道,如果将sum.apply(…)的第一个参数设置为null,那么就意味着我们并不关心sum在执行时其内部的this指向谁。而Function.apply.bind(sum, null)目的就是将sum.apply(…)的第一个参数固定为null(其中,Function.apply.bind(sum, null)等价于sum.apply.bind(sum, null))。
所以最终我们得到的foo函数就是sum.apply(null, [10, 20]); [10,20]会拆开成10和20传递给sum(…)。
那么我们再回到最开始的那个Promise的例子,传递给.then()的Promise决议值就是数组[10,20],.then函数的第一个参数(通常我们称之为fulfilled(…)函数)就相当于我们刚才创建的foo(…),执行foo([10, 20])输出结果就是10,20。
2.Function.bind.apply(…)
那么类似的问题就还剩Function.bind.apply(…)。
我第一次见到这样的代码是在《你不知道的JS》中卷的2.4小节。讲回调的时候。针对回调的调用过早的问题,有经验的开发者们给出了这样的解决方式(当然ES6之后解决回调函数调用过早的问题还是倾向于借助Promise机制):
function asyncify(fn) {
var orig_fn = fn,
intv = setTimeout( function(){
intv = null;
if (fn) fn();
}, 0 )
;
fn = null;
return function() {
// 触发太快,在定时器intv触发指示异步转换发生之前?
if (intv) {
fn = orig_fn.bind.apply(
orig_fn,
// 将包装函数的`this`加入`bind(..)`调用的
// 参数,同时currying其他所有的传入参数
[this].concat( [].slice.call( arguments ) )
);
}
// 说明没有过早触发,这里已经是异步
else {
// 调用原来的函数
orig_fn.apply( this, arguments );
}
};
}
和前面类似,我们将orig_fn.bind.apply(orig_fn, args)拆成两部分来看:函数orig_fn.bind(…)和.apply(orig_fn, args)。根据.apply(…)的定义,orig_fn.bind.apply(orig_fn, args)其实就意味着我们将orig_fn.bind(…)函数的this指向orig_fn,然后.apply(orig_fn, args)的第二个参数会将剩下的参数传递给orig_fn.bind(…)函数。
那么我们现在分析一下剩下的参数([this].concat( [].slice.call( arguments ))都是什么吧,首先arguments是外界传入的其余参数(return function(…)这个函数传入的参数),接下来我们借助[].slice.call( arguments )将其转化为一个参数数组,备用。由于.bind(…)的第一个参数为在 origin_fn 调用中用到的 this (我们在前一段就已经提到过,这个this其实就指向orig_fn),所以使用 [this] 将构造的参数数组中的第一个参数设置为 this 。[this]再与我们前面的备用数组拼接起来,一同传递给.bind(…)。
此时,.bind(…)的第一个参数就是this,剩余参数就是外界传入的参数。所以,除了传递给orig_fn.bind(…)的第一个参数this,其余的参数都会作为柯里化参数(预设值)。
在这里的关键点是:.bind(…) 函数是通过 .apply(…) 调用的,所以 .bind(…) 自身所需要的 this 对象是一个函数(函数也是对象,在这里即 origin_fn)。
---------------------
版权声明:本文为CSDN博主「Typhoonnnnn」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_37787381/article/details/81509361
Function.apply.bind()与Function.apply.bind()的更多相关文章
- JavaScript的函数call和apply的区别、以及bind方法
1.call和apply的定义和区别 call和apply的作用一样,唯一不同的是:接受的参数不同. apply:方法能够劫持另一个对象的方法,继承另一个对象的属性. Funciton.apply(o ...
- JavaScript中的bind,call和apply函数的用法和区别
一直没怎么使用过JavaScript中的bind,call和apply, 今天看到一篇比较好的文章,觉得讲的比较透彻,所以记录和总结如下 首先要理解的第一个概念,JavaScript中函数调用的方式, ...
- Function.prototype.call 和 Function.prototype.apply 的区别
call和apply函数是function函数的基本属性,都可以用于更改函数对象和传递参数,是前端工程师常用的函数.具体使用方法请参考以下案列: 例如: 申明函数: var fn = function ...
- jquery阻止冒泡事件:$('span').bind("click",function(event){event.stopPropagation();})(有用源)
冒泡事件就是点击子节点,会向上触发父节点,祖先节点的点击事件. <body> <div id="content"> 外层div元素 <span> ...
- boost bind及function的简单实现
前面在做 http server 的时候,需要做一个回调的接口,要求能够绑定类的函数以及普通的函数到这个回调里,对于这种应用要求,选择 boost 的 bind 和 function 是最合适不过了, ...
- bind(),call(), apply()方法的区别是什么?
bind(),call(), apply()方法的区别是什么? 共同点:改变this指向,任何调用都不在起作用 bind() 改变this的指向,不会调用函数,返回一个新的函数 var o ={a:' ...
- C++11 bind和function用法
function是一个template,定义于头文件functional中.通过function<int(int, int)> 声明一个function类型,它是“接受两个int参数.返回 ...
- 基于boost的bind与function的一个简单示例消息处理框架
前两年开始接触boost,boost库真是博大精深:今天简单介绍一下boost中之前用到的的bind与function,感觉挺实用的,分享给大家,我对boost用的也不多,让大家见笑了. 上次文发了一 ...
- C++11绑定器bind及function机制
前言 之前在学muduo网络库时,看到陈硕以基于对象编程的方式,大量使用boost库中的bind和function机制,如今,这些概念都已引入至C++11,包含在头文件<functional&g ...
随机推荐
- 【面试突击】- SpringMVC那些事(一)
1.什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一个模块,无需中间整合 ...
- 0.UML图入门——学习《大话设计模式》笔记
<大话设计模式>中讲述了UML类图的基本用法,做此笔记加深理解. 注:上图来源于<大话设计模式> 上图中设计的关键术语为:继承.实现.聚合.组合.关联.依赖. 要想弄清楚UML ...
- vue-cli脚手架——3.0版本项目案例
一.[准备工作] node与git部分见vue-cli2.0搭建案例 vue-cli3.0是一个基于 Vue.js 进行快速开发的完整系统.有三个组件: CLI:@vue/cli 全局安装的 npm ...
- MQTT的websockets应用_转
转自:mosquitto 与websocket 的结合 前言 mosquitto 作为一个消息代理, 客户端与 mosquitto 服务端的通信时基于 MQTT 协议的, 而现在的主流 web 应用时 ...
- Linux系统下RAID5和RAID10的磁盘阵列配置
前提了解:1988年由加利福尼亚大学伯克利分校发表的文章首次提到并定义了RAID,当今CPU性能每年可提升30%-50%但硬盘仅提升7%,渐渐的已经成为计算机整体性能的瓶颈,并且为了避免硬盘的突然损坏 ...
- 【转载】用户通过WEB方式更改AD域帐户密码
用户改自己的域帐户密码一般通过以下几种方式: 加域的PC,用户直接按:Ctrl+Alt+Del键,点击:更改密码 通过exchange owa更改密码 让管理员重置密码 除了以上方式外,很多企业通过开 ...
- 2013.6.24 - OpenNE第四天
今天晚上跟师兄讨论,这那几篇论文,对于<领域多词表 达翻译对的自动抽取及其应用>那篇,我的感觉是跟实体识别不太吻合.他的大概意思就是先讲所有有可能的多词表达都找出来,然后在用C-value ...
- 用js刷剑指offer(两个链表的第一个公共结点)
题目描述 输入两个链表,找出它们的第一个公共结点. 牛客网链接 js代码 /*function ListNode(x){ this.val = x; this.next = null; }*/ fun ...
- html实战
主要html源码 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=&qu ...
- 运行Vue项目,没办法自动打开浏览器,提示“Unable to open browser. If you are running in a headless environment, please do not use the open flag.”
留坑,待解决 Unable to open browser. If you are running in a headless environment, please do not use the o ...