背景:

小明想要用数组的形式为 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

作者GitHubhttps://github.com/pspgbhu

欢迎转载,但请注明出处,谢谢!

.bind.apply() 解决 new 操作符不能用与 apply 或 call 同时使用的更多相关文章

  1. js中bind的用法,及与call和apply的区别

    call和apply的使用和区别不再做阐述,可以参考我的另一篇随笔<JavaScript中call和apply方法的使用>(https://www.cnblogs.com/lcr-smg/ ...

  2. [每天解决一问题系列 - 0001] Javascript apply和 call对比

    相同点: 每个函数都包含这两个原生的方法 他们两个的效果是一样的,用于在特定的作用域下执行函数,本质上是设置函数内this对象的值. 不同点: 传入的参数类型不同 . apply(函数作用域,arra ...

  3. .apply .call方法的区别及使用 .apply第二个参数为数组,.call第二个参数为参数列表, 相同点:第一个参数都为Function函数内部的this对象.

    Function.apply(obj,args)方法能接收两个参数 obj:这个对象将代替Function类里this对象 args:这个是数组,它将作为参数传给Function(args--> ...

  4. 使用call、apply和bind解决js中烦人的this,事件绑定时的this和传参问题

    1.什么是this 在JavaScript中this可以是全局对象.当前对象或者任意对象,这完全取决于函数的调用方式,this 绑定的对象即函数执行的上下文环境(context). 为了帮助理解,让我 ...

  5. javascript中apply、call和bind的区别及方法详解

    文章目录   apply.call apply.call 区别 apply.call实例 数组之间追加 获取数组中的最大值和最小值 验证是否是数组(前提是toString()方法没有被重写过) 类(伪 ...

  6. JS中的call、apply、bind方法详解

    bind 是返回对应函数,便于稍后调用:apply .call 则是立即调用 . apply.call 在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(co ...

  7. JS核心系列:浅谈 call apply 与 bind

    在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...

  8. 【优雅代码】深入浅出 妙用Javascript中apply、call、bind

    这篇文章实在是很难下笔,因为网上相关文章不胜枚举. 巧合的是前些天看到阮老师的一篇文章的一句话: “对我来说,博客首先是一种知识管理工具,其次才是传播工具.我的技术文章,主要用来整理我还不懂的知识.我 ...

  9. Javascript中call,apply,bind方法的详解与总结

    在 javascript之 this 关键字详解 文章中,谈及了如下内容,做一个简单的回顾: 1.this对象的涵义就是指向当前对象中的属性和方法. 2.this指向的可变性.当在全局作用域时,thi ...

随机推荐

  1. protected private public 的区别

    1.public,protected,private是Java里用来定义成员的访问权限的,另外还有一种是"default",也就是在成员前不加任何权限修饰符.如:    publi ...

  2. 跑马灯、短信与反射EditText

    1.1.跑马灯功能 Android自带支持跑马灯功能,实现此功能需要设置已下属性: android:ellipsize="marquee" // 必选,跑马灯样式 android: ...

  3. 兼容主流浏览器的js原生函数封装

    1.获取和修改垂直滚动条的滚动距离 //获取滚动条滚动距离function getScrollTop(){ var fromTop=document.documentElement.scrollTop ...

  4. Java语言定义的线程状态分析

    说到线程,一定要谈到线程状态,不同的状态说明线程正处于不同的工作机制下,不同的工作机制下某些动作可能对线程产生不同的影响. Java语言定义了6中状态,而同一时刻,线程有且仅有其中的一种状态.要获取J ...

  5. CSS前端开发学习总结、一

    1. 属性选择器: 2. CSS伪类选择器: 3. CSS伪元素: 4. CSS优先级: 5. 行内标签: 6. 块级标签: 7. Display: 8. Line-height:行高 9. text ...

  6. Alamofire源码解读系列(十)之序列化(ResponseSerialization)

    本篇主要讲解Alamofire中如何把服务器返回的数据序列化 前言 和前边的文章不同, 在这一篇中,我想从程序的设计层次上解读ResponseSerialization这个文件.更直观的去探讨该功能是 ...

  7. C++ 拷贝控制和资源管理,智能指针的简单实现

    C++ 关于拷贝控制和资源管理部分的笔记,并且介绍了部分C++ 智能指针的概念,然后实现了一个基于引用计数的智能指针.关于C++智能指针部分,后面会有专门的研究. 通常,管理类外资源的类必须定义拷贝控 ...

  8. 使用Vagrant打造开发环境

    1.安装Oracle VM VirtualBox.vagrant,安装完成需重启电脑 Oracle VM VirtualBox安装包下载:https://www.virtualbox.org/wiki ...

  9. Java进阶之内存管理与垃圾回收

    Java是在JVM所虚拟出的内存环境中运行的.内存分为栈(stack)和堆(heap)两部分.我们将分别考察这两个区域. 栈 在Java中,JVM中的栈记录了线程的方法调用.每个线程拥有一个栈.在某个 ...

  10. 老李分享: 并行计算基础&编程模型与工具 2

    2.并行编程模型和工具 – MPI – MPI(Message Passing Interface)是一种消息传递编程模型,服务于进程通信.它不特指某一个对它的实现,而是一种标准和规范的代表,它是一种 ...