Ты не понял. Никто не говорит о том, что нужно отказаться от 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, время: 11:47. |