我认为 OP 正在寻找的内容与此严格相似:
var nums = [1, 2, 3];
var strs = nums.map(String);
//=> ['1', '2', '3']; // array of strings
我认为原因是这非常优雅,无论是在像上面这样的简单类型转换操作中,还是在更有趣的任务中,比如将某物的一种表示形式转换为不同的表示形式,如下所示:
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
这个问题似乎在于,通过将构造函数传递给Array.map 创建的新对象是window 的扩展版本;也就是说,构造函数中的this 指的是全局范围,这很糟糕,因为(1)将道具挂在window 上不是您的目标,并且(2)您以这种方式创建的对象不是唯一的实例。
就其价值而言,最初的类型转换示例也不是人们想象的那样,因为:
strs[0] instanceof String
//=> false // UGH!
到目前为止,我提出的唯一解决方案需要以不同的方式编写构造函数——这显然不能用于像 Date 这样的原生类型:
function Human(animal) {
var h = new Object();
h.species = 'human';
h.name = animal.name;
return h;
}
var humans = animals.map(Human);
通过将返回值定义为一个新对象,我们切断了全局作用域和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);
在这种情况下,返回 JSON 并不一样好,因为似乎没有任何有效的方法来设置对象文字的原型;即使你可以,你也永远不希望 this 是真的:
myObject.hasOwnProperty('prototype');
//=> true // only if myObject = { prototype: HumanProto }
我认为确保新对象具有所需原型的最佳方法是将可能的原型作为参数传递给new Object()。
这种模式理想吗?我不知道。这似乎有点奇怪,因为现在有两个符号与创建人类相关:Human 构造函数,HumanProto 显式原型。更重要的是,如果您已经拥有了一个有趣的自定义类生态系统,而这些类的编写方式与此模式不兼容,那么这似乎是一个真正的障碍。
那里可能有更好的方法。也许有人会发布它。