Это может помочь разделить цепочки прототипов на две категории.
Рассмотрим конструктор:
function Person() {}
Значение Object.getPrototypeOf(Person)
является функцией. На самом деле это Function.prototype
. Поскольку Person
был создан как функция, он разделяет тот же объект функции-прототип, что и все функции. Это то же самое, что и Person.__proto__
, но это свойство не должно использоваться. В любом случае, с Object.getPrototypeOf(Person)
вы эффективно поднимаетесь по лестнице того, что называется цепочкой прототипов.
Цепочка в направлении вверх выглядит следующим образом:
& nbsp; & nbsp; & nbsp; Person
→ Function.prototype
→ Object.prototype
(конечная точка)
Важно то, что эта цепочка прототипов имеет мало общего с объектами, которые Person
может построить . Эти сконструированные объекты имеют свою собственную цепочку прототипов, и эта цепочка потенциально может не иметь близких предков, общих с упомянутой выше
.
Возьмем, к примеру, этот объект:
var p = new Person();
p не имеет прямого отношения прототип-цепочка с Person . Их отношения разные. Объект p имеет свою собственную цепочку прототипов. Используя Object.getPrototypeOf
, вы обнаружите, что цепочка выглядит следующим образом:
& nbsp; & nbsp; & nbsp; p
→ Person.prototype
→ Object.prototype
(конечная точка)
В этой цепочке нет функционального объекта (хотя это может быть).
Таким образом, Person
кажется связанным с двумя видами цепей, которые живут своей жизнью. Чтобы «перепрыгнуть» из одной цепочки в другую, вы используете:
.prototype
: перейти от цепочки конструктора к цепочке созданного объекта. Таким образом, это свойство определяется только для функциональных объектов (так как new
можно использовать только для функций).
.constructor
: перейти от цепочки созданного объекта к цепочке конструктора.
Вот визуальное представление двух задействованных прототипов, представленных в виде столбцов:
[1183]
Подводя итог:
Свойство
prototype
не дает информации о цепочке прототипов субъекта , но об объектах , созданных субъектом.
Не удивительно, что название свойства prototype
может привести к путанице. Возможно, было бы яснее, если бы это свойство было названо prototypeOfConstructedInstances
или что-то в этом роде.
Вы можете переключаться между двумя цепочками прототипов:
Person.prototype.constructor === Person
Эта симметрия может быть нарушена путем явного присвоения другого объекта свойству prototype
(подробнее об этом позже).
Person.prototype
- это объект, который был создан одновременно с созданием функции Person
. Он имеет Person
в качестве конструктора, хотя этот конструктор еще не выполнялся. Итак, два объекта создаются одновременно:
Person
Оба являются объектами, но они выполняют разные роли: объект функции создает , в то время как другой объект представляет прототип любого объекта, который будет создавать функция. Прототип объекта станет родителем построенного объекта в его цепочке прототипов.
Поскольку функция также является объектом, она также имеет своего родителя в своей собственной цепочке прототипов, но напомним, что эти две цепочки связаны с разными вещами.
Вот некоторые равенства, которые могут помочь понять проблему - все эти печати true
:
function Person() {};
// This is prototype chain info for the constructor (the function object):
console.log(Object.getPrototypeOf(Person) === Function.prototype);
// Step further up in the same hierarchy:
console.log(Object.getPrototypeOf(Function.prototype) === Object.prototype);
console.log(Object.getPrototypeOf(Object.prototype) === null);
console.log(Person.__proto__ === Function.prototype);
// Here we swap lanes, and look at the constructor of the constructor
console.log(Person.constructor === Function);
console.log(Person instanceof Function);
// Person.prototype was created by Person (at the time of its creation)
// Here we swap lanes back and forth:
console.log(Person.prototype.constructor === Person);
// Although it is not an instance of it:
console.log(!(Person.prototype instanceof Person));
// Instances are objects created by the constructor:
var p = new Person();
// Similarly to what was shown for the constructor, here we have
// the same for the object created by the constructor:
console.log(Object.getPrototypeOf(p) === Person.prototype);
console.log(p.__proto__ === Person.prototype);
// Here we swap lanes, and look at the constructor
console.log(p.constructor === Person);
console.log(p instanceof Person);
Хотя объект-прототип создается при создании функции конструктора, вы можете игнорировать этот объект и назначить другой объект, который следует использовать в качестве прототипа для любых последующих экземпляров, созданных этот конструктор.
Например:
function Thief() { }
var p = new Person();
Thief.prototype = p; // this determines the prototype for any new Thief objects:
var t = new Thief();
Теперь цепочка прототипов т на один шаг длиннее, чем у p :
& nbsp; & nbsp; & nbsp; & nbsp; t
→ p
→ Person.prototype
→ Object.prototype
(конечная точка)
Другая цепочка прототипов не длиннее: Thief
и Person
являются братьями и сестрами, разделяющими тот же родитель в цепочке прототипов:
& nbsp; & nbsp; & nbsp; & nbsp; Person
}
& nbsp; & nbsp; & nbsp; & nbsp; Thief
& nbsp; } → Function.prototype
→ Object.prototype
(конечная точка)
Ранее представленную графику можно затем расширить до этого (оригинальный Thief.prototype
опущен):
Синие линии представляют цепочки прототипов, другие цветные линии представляют другие отношения:
GPL
http: / /www.icsharpcode.net/OpenSource/SharpZipLib/
ИЛИ менее ограничительный Ms-PL
http://www.codeplex.com/DotNetZip
Чтобы завершить этот ответ, инфраструктура .net имеет ZipPackage Мне это не удалось.
Я бы предпочел SharpZiplib Найдите пример кода, чтобы Распаковать файлы в .Net C #
Если вы хотите использовать сжатие 7-zip, ознакомьтесь со статьей Питера Бромберга EggheadCafe . Осторожно: исходный код LZMA для C # не содержит комментариев xml (на самом деле, их очень мало).
В прошлом я использовал DotNetZip (MS-PL), SharpZipLib (GPL) и 7ZIP SDK для C # (общественное достояние). Все они отлично работают и имеют открытый исходный код.
Я бы выбрал DotNetZip в этой ситуации, и вот пример кода со страницы Примеры C # :
using (ZipFile zip = ZipFile.Read(ExistingZipFile))
{
foreach (ZipEntry e in zip)
{
e.Extract(TargetDirectory);
}
}
DotNetZip прост в использовании. Вот пример распаковки
using (var zip = Ionic.Zip.ZipFile.Read("archive.zip"))
{
zip.ExtractAll("unpack-directory");
}
. Если у вас есть более сложные задачи, например, вы хотите выбирать, какие записи извлекать, или если есть пароли, или если вы хотите контролировать имена путей извлеченных файлов и т. Д. и т. д. вариантов много. Дополнительные примеры см. В файле справки .
DotNetZip распространяется бесплатно и с открытым исходным кодом.
Have a look to my small library: https://github.com/jaime-olivares/zipstorer