Ты не понял. Никто не говорит о том, что нужно отказаться от new и использовать Object.create - это, конечно, бред. Object.create надо использовать в функции inherits, ибо нам нужен чистый объект с [[Prototype]], равным прототипу наследуемого класса, без всякой хрени от конструктора.
Цитата:
|
Цитата:
|
Цитата:
Child.prototype.constructor = Child; |
Цитата:
|
Цитата:
|
Кстати, ничего страшного не будет, если я стандартному объекту добавлю метод, чтобы наследование получилось более изящным с точки зрения синтаксиса:
Object.prototype.extends = function(parent) { this.prototype = Object.create(parent); this.prototype.constructor = this; }; var Interface = { fd : "default descriptor" }; function Class1() {}; Class1.extends(Interface); function Class2() {}; Class2.extends(Interface); Class1.prototype.fd = "class1 descriptor"; var obj1 = new Class1(); var obj2 = new Class2(); //var obj = new Interface(); //ошибка, так как нельзя создать экземпляр виртуального класса alert(obj1.fd); alert(obj2.fd); |
Voronar, только не таким образом, ибо:
Object.prototype.extends = function(){ alert('extends') }; var newObj = {foo: 'bar'}; for(var key in newObj) alert(key);это может поломать чужой код. Надо примерно так: Object.defineProperty(Object.prototype, 'extends', { value: function(){}, enumerable: *!*false*/!*, writable: true, configurable: true }); |
Aetae
Спасибо, и вправду классная вещь этот Object.defineProperty(). |
Цитата:
Object.prototype.extends = function(){ alert('extends') }; var newObj = {foo: 'bar'}; for(var key in newObj) {if(!(newObj.hasOwnProperty(key))) break; alert(key)}; Тот кто итерирует, должен понимать, что и зачем он итерирует. А проблемы дебила шерифа не е*ут. |
Voronar,
Если нужна поддержка IE-8, забудь, если я не ошибаюсь, не поддерживает он эту хрень, недавно тема тут была. |
Voronar,
Вообще, ящетаю, "Безопасное" расширение нативных объектов, могло бы выглядеть вот так Object.prototype._=function(f){return f(this)} show=function(x){console.log(x)} sum=function(x){console.log(x+x)} ;({a: 1})._(show) // { a: 1 } ;1.._(sum) // 2 Расширяем одной функцией, а затем через каллбэк дергаем как хочем. Одну ф-цию задокументировать и запомнить -- не проблема. И не надо никаких сраных костылей enumerable и пр. |
Цитата:
Voronar, слушать terminator-101 и kostyanet(скорее всего это вообще одно лицо) следует с осторожностью.(обрати внимание на карму) Они живут в своём маленьком трололо мире, слабо связанном с действительностью. Иногда чего дельного и могут сказать в моменты просветления, но в целом.. |
Цитата:
Цитата:
class Parent { someMethod(); } class Child prototype Parent.prototype {}; console.log((new Child).__proto__ == Parent.prototype); //true |
Цитата:
|
Цитата:
По-идее, то что он написал, это тоже самое, что ({}).__proto__. Вроде, именно так и расширяются нативные объекты. А в саму то функцию что толку писать? alert(Object.prototype===({}.__proto__)) // true |
Erolast,
Object.__proto__.one=1 Object.prototype.ten=10 alert([{}.one, {}.ten]) |
Цитата:
Object.defineProperty(Function.prototype, "extends", { writable: true, configurable: true, enumerable: false, value: function(){} }); Цитата:
|
Цитата:
Function.prototype.extends=function(){} console.log(function(){}.extends, ({}).extends, "foo".extends) // [Function] undefined undefined за исключением сраного enumerable Ты расширил функцию, а речь шла за объекты. Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
|
:D
"Я нихера не понимаю, сейчас-то просто занят, да и вообще там лажа, да и вообще ты слил." |
Erolast, забей ты на этого нуба :)
|
Erolast,
Я тебе не за то говорил, а за последующие твои лажовые утверждения по-поводу расширения объекта. А к тому коду мы еще вернемся, не переживай. |
Цитата:
|
Возвращаемся к истинному сабжу. После обдумывания о концепции чистого виртуального класса а-ля C++, я пришёл к выводу, что на языке JavaScript такую концепцию не имеет смысла реализовывать, по крайней мере в таком виде.
Ещё раз повторю, что подразумевается под чистым виртуальным классом (ЧВК). ЧВК в C++ - это по сути реализация концепция ООП-интерфейсов. То есть мы объявляем ЧВК только в качестве описание для дальнейшей реализации только в наследуемых классах. Например, создадим ЧВК IODevice и производные от него классы Device1 и Device2. //C++ code: #include <stdio.h> #include <string> class IODevice { protected: std::string descriptor; public: virtual int open() = 0; virtual ~IODevice() {} }; class Device1 : public IODevice { public: Device1(std::string _descriptor) //constructor { descriptor = _descriptor; } int open() { printf("%s opening...\n", descriptor.c_str()); return 0; } ~Device1() {} }; class Device2 : public IODevice { public: Device2(std::string _descriptor) //constructor { descriptor = _descriptor; } int open() { printf("%s opening...\n", descriptor.c_str()); return 0; } }; int main() { Device1* dev1 = new Device1("Device1"); Device2* dev2 = new Device2("Device2"); //IODevice* dev = new IODevice(); //error: cannot allocate an object of abstract type 'IODevice' dev1->open(); dev2->open(); delete dev2; delete dev1; return 0; } Можно запустить пример и убедиться, что для каждого класса запускается своя версия метода. Возвращаюсь к JavaScript. Ведь нет смысла в том, чтобы создавать объект ("ЧВК"), только для того, чтобы просто иметь там свойства, которые по сути и не будут использоваться - это только расход памяти. Я вижу такую реализацию на JS: "use strict"; Object.defineProperty(Object.prototype, "extends", { value: function(parent) { this.prototype = Object.create(parent.prototype, { constructor: { value: this, writable: true, configurable: true, enumerable: false } }); arguments[1] === "INTERFACE" ? this.__interfaced__ = true : undefined; }, enumerable: false, writable: true, configurable: true }); function IODevice(fd) { if(this.constructor.hasOwnProperty("__interfaced__")) { this._descriptor = fd; } else { alert("Warning: cannot allocate an object of abstract type " + "\"" + this.constructor.name + "\""); return new Error("Cannot allocate an object of abstract type " + "\"" + this.constructor.name + "\""); } } function Device1(fd) { IODevice.call(this, fd); } Device1.extends(IODevice, "INTERFACE"); Device1.prototype.open = function() { console.log(this._descriptor + " opening..."); }; function Device2(fd) { IODevice.call(this, fd); } Device2.extends(IODevice, "INTERFACE"); Device2.prototype.open = function() { console.log(this._descriptor + " opening..."); }; var dev1 = new Device1("Device1"); var dev2 = new Device2("Device2"); var dev = new IODevice("dev"); dev1.open(); dev2.open(); console.log(dev); |
Цитата:
Задачу можно решить наследованием от объекта, а не от класса: Object.defineProperty(Function.prototype, "extends", { value: function(parent) { *!*var inheritFrom = typeof parent == "function" ? parent.prototype : parent;*/!* this.prototype = Object.create(inheritFrom, { constructor: { value: this, writable: true, configurable: true, enumerable: false } }); }, enumerable: false, writable: true, configurable: true }); var IODevice = { }; function Device1() {} Device1.extends(IODevice); function Device2() {} Device2.extends(IODevice); new Device1(); new Device2(); new IODevice(); //TypeError: IODevice is not a constructor В ES6 так: var IODevice = {}; class Device1 prototype IODevice { } class Device2 prototype IODevice { } |
А как в этом случае использовать конструктор абстрактного класса, если теперь это просто объект?
Ещё такой вопрос. Если мы передаём Object.create в качестве аргумента(proto) parent.prototype, то в этом случае реализуется наследование от функции-конструктора, а если просто объект parent, то в это случае мы получаем копию parent? |
Цитата:
Цитата:
|
Цитата:
Цитата:
|
Цитата:
Цитата:
Тут важно отличать свойства [[Prototype]] и prototype. Свойство [[Prototype]] скрытое, есть у любой переменной (в том числе у примитивов) и определяет, в каком объекте будет искаться свойство, если не найдено в текущем. Доступ к нему можно получить либо с помощью геттера __proto__ (устаревший вариант), либо с помощью Object.getPrototypeOf. Свойство prototype есть у функций, оно ссылается на объект, ссылка на который будет записана в свойство [[Prototype]] объекта, сконструированного этой функцией. |
|
Извращенцы :)
|
Voronar,
Если очень нужны интерфейсы и привычка к строгой типизации можно посмотреть в сторону TypeScript |
А что перспективнее с точки зрения написания многофункциональных веб-приложений (высокопроизводительных) я-ля desktop?
1)JavaScript (+ES6, asm.js, etc.) 2)TypeScript 3)Dart |
Voronar, смешной вопрос. Да хоть brainfuck если он вам удобен, понятен и приятен в работе.
|
Часовой пояс GMT +3, время: 14:36. |