.bind.apply() 解决 new 操作符不能用与 apply 或 call 同时使用
背景:
小明想要用数组的形式为 Cls.func 传入多个参数,他想到了以下的写法:
var a = new Cls.func.apply(null, [1, 2, 3]);
然而浏览器却报错 Cls.func.apply is not a constructor。
乍一看是 new 操作符去修饰 Cls.func.apply 了,于是他又这么写:
var a = (new Cls.func).apply(null, [1, 2, 3]);
浏览器依旧报错。。。好吧,还是好好查一查相关的解决方法吧,还好这是个好时代,没有什么是网上查不出来的。
思路:
在网上找到了非常关键的几个解决方案和思路。
参考链接 http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
关键摘抄:
function newCall(Fn) {
return new (Function.prototype.bind.apply(Fn, arguments));
// or even
// return new (Fn.bind.apply(Fn, arguments));
// if you know that Fn.bind has not been overwritten
}
// It can be used as follows:
var s = newCall(Fn, a, b, c);
// or even directly:
var a = new (Function.prototype.bind.call(Fn, null, 1, 2, 3));
var a = new (Function.prototype.bind.apply(Fn, [null, 1, 2, 3]));
以上关键就在于 .bind.apply() 或 .bind.call() 这中写法。
Function.prototype.bind() 等同于 Fn.bind() 会创建一个新的函数,第一个参数为新函数的 this 指向,而后多个参数为绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
先分析一下 Function.prototype.bind.call() 这种写法:
var a = new (Function.prototype.bind.call(Fn, null, 1, 2, 3));
call() 接受多个参数,第一个参数为函数执行的上下文环境,后面的参数会依次传递给前面的 bind 作为参数。
所以 bind() 接到的参数为 bind(null, 1, 2, 3)。所以上面的那种写法就等同于:
var a = new ( Fn.bind(null, 1, 2, 3)() );
同理再推导 Function.prototype.bind.apply() 写法:
var a = new (Function.prototype.bind.apply(Fn, [null, 1, 2, 3]);
call() 接受两个参数,第一个参数为函数执行的上下文环境,第二个参数为数组,数组的每一项会一次作为 bind() 的参数,因此 bind() 接受到的参数也为 bind(null, 1, 2, 3)。因此也等价于:
var a = new ( Fn.bind(null, 1, 2, 3)() );
解决:
有了上面的推导,小明这时候就可以轻易的写出自己想要的结果了,同时为了拓展方便,小明决定写一个通用的方法:
function newApply(Fn, argsAry) {
argsAry.unshift(null);
return new (Fn.bind.apply(Fn, argsAry));
}
// 调用
newApply(Cls.func, [1, 2, 3]) // well done !!
作者博客:pspgbhu http://www.cnblogs.com/pspgbhu/
原文链接:http://www.cnblogs.com/pspgbhu/p/6796795.html
作者GitHub:https://github.com/pspgbhu
欢迎转载,但请注明出处,谢谢!
.bind.apply() 解决 new 操作符不能用与 apply 或 call 同时使用的更多相关文章
- js中bind的用法,及与call和apply的区别
call和apply的使用和区别不再做阐述,可以参考我的另一篇随笔<JavaScript中call和apply方法的使用>(https://www.cnblogs.com/lcr-smg/ ...
- [每天解决一问题系列 - 0001] Javascript apply和 call对比
相同点: 每个函数都包含这两个原生的方法 他们两个的效果是一样的,用于在特定的作用域下执行函数,本质上是设置函数内this对象的值. 不同点: 传入的参数类型不同 . apply(函数作用域,arra ...
- .apply .call方法的区别及使用 .apply第二个参数为数组,.call第二个参数为参数列表, 相同点:第一个参数都为Function函数内部的this对象.
Function.apply(obj,args)方法能接收两个参数 obj:这个对象将代替Function类里this对象 args:这个是数组,它将作为参数传给Function(args--> ...
- 使用call、apply和bind解决js中烦人的this,事件绑定时的this和传参问题
1.什么是this 在JavaScript中this可以是全局对象.当前对象或者任意对象,这完全取决于函数的调用方式,this 绑定的对象即函数执行的上下文环境(context). 为了帮助理解,让我 ...
- javascript中apply、call和bind的区别及方法详解
文章目录 apply.call apply.call 区别 apply.call实例 数组之间追加 获取数组中的最大值和最小值 验证是否是数组(前提是toString()方法没有被重写过) 类(伪 ...
- JS中的call、apply、bind方法详解
bind 是返回对应函数,便于稍后调用:apply .call 则是立即调用 . apply.call 在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(co ...
- JS核心系列:浅谈 call apply 与 bind
在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...
- 【优雅代码】深入浅出 妙用Javascript中apply、call、bind
这篇文章实在是很难下笔,因为网上相关文章不胜枚举. 巧合的是前些天看到阮老师的一篇文章的一句话: “对我来说,博客首先是一种知识管理工具,其次才是传播工具.我的技术文章,主要用来整理我还不懂的知识.我 ...
- Javascript中call,apply,bind方法的详解与总结
在 javascript之 this 关键字详解 文章中,谈及了如下内容,做一个简单的回顾: 1.this对象的涵义就是指向当前对象中的属性和方法. 2.this指向的可变性.当在全局作用域时,thi ...
随机推荐
- protected private public 的区别
1.public,protected,private是Java里用来定义成员的访问权限的,另外还有一种是"default",也就是在成员前不加任何权限修饰符.如: publi ...
- 跑马灯、短信与反射EditText
1.1.跑马灯功能 Android自带支持跑马灯功能,实现此功能需要设置已下属性: android:ellipsize="marquee" // 必选,跑马灯样式 android: ...
- 兼容主流浏览器的js原生函数封装
1.获取和修改垂直滚动条的滚动距离 //获取滚动条滚动距离function getScrollTop(){ var fromTop=document.documentElement.scrollTop ...
- Java语言定义的线程状态分析
说到线程,一定要谈到线程状态,不同的状态说明线程正处于不同的工作机制下,不同的工作机制下某些动作可能对线程产生不同的影响. Java语言定义了6中状态,而同一时刻,线程有且仅有其中的一种状态.要获取J ...
- CSS前端开发学习总结、一
1. 属性选择器: 2. CSS伪类选择器: 3. CSS伪元素: 4. CSS优先级: 5. 行内标签: 6. 块级标签: 7. Display: 8. Line-height:行高 9. text ...
- Alamofire源码解读系列(十)之序列化(ResponseSerialization)
本篇主要讲解Alamofire中如何把服务器返回的数据序列化 前言 和前边的文章不同, 在这一篇中,我想从程序的设计层次上解读ResponseSerialization这个文件.更直观的去探讨该功能是 ...
- C++ 拷贝控制和资源管理,智能指针的简单实现
C++ 关于拷贝控制和资源管理部分的笔记,并且介绍了部分C++ 智能指针的概念,然后实现了一个基于引用计数的智能指针.关于C++智能指针部分,后面会有专门的研究. 通常,管理类外资源的类必须定义拷贝控 ...
- 使用Vagrant打造开发环境
1.安装Oracle VM VirtualBox.vagrant,安装完成需重启电脑 Oracle VM VirtualBox安装包下载:https://www.virtualbox.org/wiki ...
- Java进阶之内存管理与垃圾回收
Java是在JVM所虚拟出的内存环境中运行的.内存分为栈(stack)和堆(heap)两部分.我们将分别考察这两个区域. 栈 在Java中,JVM中的栈记录了线程的方法调用.每个线程拥有一个栈.在某个 ...
- 老李分享: 并行计算基础&编程模型与工具 2
2.并行编程模型和工具 – MPI – MPI(Message Passing Interface)是一种消息传递编程模型,服务于进程通信.它不特指某一个对它的实现,而是一种标准和规范的代表,它是一种 ...