文档章节

将.apply()与'new'运算符配合使用。 这可能吗?

 技术盛宴
发布于 01/27 09:43
字数 757
阅读 118
收藏 0

在JavaScript中,我想创建一个对象实例(通过new运算符),但是将任意数量的参数传递给构造函数。 这可能吗?

我想做的是这样的(但是下面的代码不起作用):

function Something(){
    // init stuff
}
function createSomething(){
    return new Something.apply(null, arguments);
}
var s = createSomething(a,b,c); // 's' is an instance of Something

答案

从这里的响应中可以明显看出,没有使用new运算符调用.apply()内置方法。 但是,人们提出了一些非常有趣的解决方案。

我更喜欢的解决方案是Matthew Crumley的解决方案(我已对其进行了修改以传递arguments属性):

var createSomething = (function() {
    function F(args) {
        return Something.apply(this, args);
    }
    F.prototype = Something.prototype;

    return function() {
        return new F(arguments);
    }
})();

#1楼

任何函数(甚至是构造函数)都可以使用可变数量的参数。 每个函数都有一个“参数”变量,可以使用[].slice.call(arguments)转换为数组。

function Something(){
  this.options  = [].slice.call(arguments);

  this.toString = function (){
    return this.options.toString();
  };
}

var s = new Something(1, 2, 3, 4);
console.log( 's.options === "1,2,3,4":', (s.options == '1,2,3,4') );

var z = new Something(9, 10, 11);
console.log( 'z.options === "9,10,11":', (z.options == '9,10,11') );

上面的测试产生以下输出:

s.options === "1,2,3,4": true
z.options === "9,10,11": true

#2楼

@Matthew我认为最好也修复构造函数属性。

// Invoke new operator with arbitrary arguments
// Holy Grail pattern
function invoke(constructor, args) {
    var f;
    function F() {
        // constructor returns **this**
        return constructor.apply(this, args);
    }
    F.prototype = constructor.prototype;
    f = new F();
    f.constructor = constructor;
    return f;
}

#3楼

如果您对基于评估的解决方案感兴趣

function createSomething() {
    var q = [];
    for(var i = 0; i < arguments.length; i++)
        q.push("arguments[" + i + "]");
    return eval("new Something(" + q.join(",") + ")");
}

#4楼

您可以将init东西移到Something原型的单独方法中:

function Something() {
    // Do nothing
}

Something.prototype.init = function() {
    // Do init stuff
};

function createSomething() {
    var s = new Something();
    s.init.apply(s, arguments);
    return s;
}

var s = createSomething(a,b,c); // 's' is an instance of Something

#5楼

这是一个通用的解决方案,可以使用参数数组调用任何构造函数(当调用函数时,本机构造函数的行为不同,例如StringNumberDate等)。

function construct(constructor, args) {
    function F() {
        return constructor.apply(this, args);
    }
    F.prototype = constructor.prototype;
    return new F();
}

通过调用construct(Class, [1, 2, 3])创建的对象与使用new Class(1, 2, 3)创建的对象相同。

您还可以制作一个更具体的版本,因此不必每次都通过构造函数。 这也稍微有点效率,因为它不需要每次调用它时都创建一个内部函数的新实例。

var createSomething = (function() {
    function F(args) {
        return Something.apply(this, args);
    }
    F.prototype = Something.prototype;

    return function(args) {
        return new F(args);
    }
})();

创建和调用外部匿名函数的原因是为了防止函数F污染全局名称空间。 有时称为模块模式。

[更新]

对于那些想在TypeScript中使用它的人,因为如果F返回任何内容,TS会给出错误:

function construct(constructor, args) {
    function F() : void {
        constructor.apply(this, args);
    }
    F.prototype = constructor.prototype;
    return new F();
}

本文转载自:https://stackoom.com/question/6k05/将-apply-与-new-运算符配合使用-这可能吗

粉丝 0
博文 1083
码字总数 0
作品 0
深圳
高级程序员
私信 提问
加载中

评论(0)

call、apply、bind方法的使用及js原生实现(含this、arguments、rest、扩展运算符与结构赋值简单使用)

讲解call、apply及bind对this修改指针指向方法的使用、区别及实现。 前言 本文主要内容是对call、apply及bind的功能及使用方法进行介绍,之后会通过js原生实现这三种方法,让我们更深入地了解...

LINNN
2019/09/19
0
0
SQL Server-聚焦APPLY运算符(二十七)

前言 其实有些新的特性在SQL Server早就已经出现过,但是若非系统的去学习数据库你会发现在实际项目中别人的SQL其实是比较复杂的,其实利用新的SQL Server语法会更加方便和简洁,从本节开始我...

jeffcky
2016/12/18
0
0
SQL Server-聚焦APPLY运算符

初探APPLY运算符 APPLY运算符是一个非常强大的表运算符,但是APPLY不是标准的,相对应的标准叫做LATERAL,但是此标准并未在SQL Server中实现。像所有表运算符一样,该运算符用于查询的FROM子...

技术小阿哥
2018/01/01
0
0
函数式编程之-重新认识泛型(2)

回顾上一节,为了丰富建模类型,编程语言引入了泛型,例如Optional,Result等。我们把泛型也叫做类型提升(lifting),这样带来的问题是以往的函数不能再适应提升类型,试想之前已经存在一个a...

.NET西安社区
2018/08/19
0
0
JavaScript求数组的最大值与最小值

版权声明:本文为博主原创文章,欢迎读者转载学习,转载请注明文章出处。 https://blog.csdn.net/qq_37338983/article/details/82953887 在JavaScript中,当要求一串数中的最大值或最小值时,...

Bruce_wjh
2018/10/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

00-Java 面试准备

面试之前 面试前准备简历需要注意的几个方面: 写简历、改简历,这个一定要干的。简历有两个作用,一个是吸引别人,能让别人邀请你去面试,这是前提;另一个是引导面试的人,让面试的人问你所...

源程序
今天
54
0
OSChina 周二乱弹 —— 大王(@罗马的王)颜值制霸Osc社区

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @巴拉迪维 :Lunik的单曲《Seeing You Soar》 I hope you’re smiling,When seeing me soar. #今日歌曲推荐# 《Seeing You Soar》- Lunik 手...

小小编辑
今天
83
0
wordcount代码

1.写出map类 public class WCMapper extends Mapper<LongWritable,Text,Text,LongWritable>{ @Override protected void map(LongWritable key,Text value,Context context)throws IOExcepti......

七宝1
今天
59
0
Spring Batch 小任务(Tasklet)步骤

Chunk-Oriented Processing不是处理 step 的唯一方法。 考虑下面的一个场景,如果你仅仅需要调用一个存储过程,你可以在 ItemReader 中实现这个调用,然后在存储过程完成调用后返回 null。这...

honeymoose
今天
67
0
Linux日志分析

1. Linux日志文件的类型 2. 系统服务日志 2.1 syslogd的简介 2.2 syslogd的配置和使用 2.3 日志的安全性设置 2.4 远程日志记录服务 3. 日志的轮替 3.1 logrotate简介 3.2 logrotate的配置 3....

JiaMing
昨天
67
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部