将构造函数传递给Array.map?

set*_*set 14 javascript arrays constructor map prototype-programming

我该怎么做这样的事情:

var a = [1,2,3,4];
a.map(Date.constructor);
Run Code Online (Sandbox Code Playgroud)

此代码在Google V8上引发错误:

SyntaxError: Unexpected number
Run Code Online (Sandbox Code Playgroud)

我也尝试过:

a.map(Date.constructor, Date.prototype)
Run Code Online (Sandbox Code Playgroud)

结果相同.

Tom*_*Tom 7

我认为 OP 正在寻找的内容与此严格类似:

var nums = [1, 2, 3];
var strs = nums.map(String);
//=> ['1', '2', '3']; // array of strings
Run Code Online (Sandbox Code Playgroud)

我认为原因是这真的很优雅,无论是在像上面这样的简单类型转换操作中,还是在更有趣的任务中,比如将某事物的一种表示形式转换为不同的表示形式,如下所示:

function MyCoolObject(oldObject) {
    // generates new object by consuming old one
    // maybe attach some cool class methods via prototype
    return this;
}

var newList = oldList.map(MyCoolObj);
//=> array of MyCoolObj based on oldObject
Run Code Online (Sandbox Code Playgroud)

问题似乎在于,通过将构造函数传递给 来创建新对象时Array.map,是 ; 的扩展版本window。也就是说,this在构造函数中指的是全局范围,这很糟糕,因为(1)你的目标不是挂道具window,(2)你以这种方式创建的对象不是唯一的实例。

就其价值而言,原始的类型转换示例也并非完全如此,因为:

strs[0] instanceof String
//=> false // UGH!
Run Code Online (Sandbox Code Playgroud)

到目前为止,我想出的唯一解决方案需要以不同的方式编写构造函数——这显然不能用于本机类型,例如Date

function Human(animal) {
    var h = new Object();
    h.species = 'human';
    h.name = animal.name;
    return h;
}

var humans = animals.map(Human);
Run Code Online (Sandbox Code Playgroud)

通过将返回值定义为一个新对象,我们切断了全局作用域和this; 至少,这就是我认为正在发生的事情。(您也可以返回 JSON 文字而不是调用Object。)

如果我想让这些对象有一个有趣的原型,我必须单独定义它,然后显式附加它:

// this object will be used as the prototype for new Human instances
var HumanProto = {
    species: 'human',
    speak: function() { console.log('My name is ' + this.name); },
    canDrink: function() { return this.age >= 21; }
}

// then, in Human, make this change
var h = new Object(HumanProto);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,返回 JSON 并没有那么好,因为似乎没有任何有效的方法来设置 object-literal 的原型;即使可以,您也永远不希望是真的:

myObject.hasOwnProperty('prototype');
//=> true // only if myObject = { prototype: HumanProto }
Run Code Online (Sandbox Code Playgroud)

我认为确保新对象具有所需原型的最佳方法是将可能的原型作为参数传递给new Object().

这种模式理想吗?我不知道。看起来有点奇怪,因为现在有两个与创造人类相关的符号:Human构造函数和HumanProto显式原型。更重要的是,如果您已经拥有一个有趣的自定义类生态系统,而这些类的编写并不与此模式兼容,那么这似乎是一个真正的障碍。

可能有更好的出路。也许有人会发布它。


set*_*set -4

Date 是一个函数,因此 Date.constructor 是函数的构造函数。Date 对象构造函数的正确调用如下所示:

Date.prototype.constructor();
Run Code Online (Sandbox Code Playgroud)

要不就:

Date();
Run Code Online (Sandbox Code Playgroud)

这里的问题是使用 array 中的时间值创建一个 Date 对象数组a,但无法调用 Date 对象构造函数并向其传递参数而不使用运算符new(ECMA-262 15.9.2)

但任何对象构造函数都可以作为函数调用,其结果与使用new运算符相同(例如 Error 对象构造函数 (ECMA-262 15.11.1))。

$ var a = ['foo','bar','baz'];
$ a.map(Error);
> [ { stack: [Getter/Setter], arguments: undefined, type: undefined, message: 'foo' },
    { stack: [Getter/Setter], arguments: undefined, type: undefined, message: 'bar' },
    { stack: [Getter/Setter], arguments: undefined, type: undefined, message: 'baz' } ]
Run Code Online (Sandbox Code Playgroud)

  • 这是错误的,这些只是对象,而不是 Error 的实例。如果您映射“.prototype.constructor”,则在调用添加到原型的函数时突然不会定义“this”。 (5认同)