Я думаю, что то, что искал 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
явный прототип.Что еще более важно, это выглядит как настоящий барьер, если у вас уже есть экосистема забавных пользовательских классов, которые не были написаны для совместимости с этим шаблоном.
Возможно, есть лучший выход.Может быть, кто-то опубликует это.