gpt4 book ai didi

javascript - 带有 Object.create 和命名构造函数的原型(prototype) OO

转载 作者:数据小太阳 更新时间:2023-10-29 04:26:30 25 4
gpt4 key购买 nike

我是从 Python 和 Smalltalk 的背景转到 Javascript 的,我很欣赏这门语言中 Self 和 Lisp 的传承。使用 ECMAScript5,我想在没有 new 运算符的情况下尝试原型(prototype) OO。

约束:

  • 创建类的可选 new 运算符
  • instanceof 的原型(prototype)链必须是正确的
  • 用于 WebInspector 调试支持的命名构造函数
  • alloc().init() 创建序列,类似于 Objective-C 和 Python

这是我为满足标准而进行的尝试:

function subclass(Class, Base) {
"use strict";
function create(self, args) {
if (!(self instanceof this))
self = Object.create(this.prototype);
var init = self.__init__;
return init ? init.apply(self, args) : self;
}
if (Base instanceof Function) Base = Base.prototype;
else if (Base===undefined) Base = Object.prototype;

Class.prototype = Object.create(Base);
Class.prototype.constructor = Class;
Class.create = create;

Class.define = function define(name, fn) { return Class.prototype[name] = fn; };
Class.define('__name__', Class.name);
return Class;
}

它似乎在一个简单的模型中工作:

function Family(){return Family.create(this, arguments)}
subclass(Family, Object);
Family.define('__init__', function __init__(n){this.name=n; return this;});

function Tribe(){return Tribe.create(this, arguments)}
subclass(Tribe, Family);
function Genus(){return Genus.create(this, arguments)}
subclass(Genus, Tribe);
function Species(){return Species.create(this, arguments)}
subclass(Species, Genus);

将类用作工厂函数:

var dog = Species('dog');
console.assert(dog instanceof Object);
console.assert(dog instanceof Family);
console.assert(dog instanceof Tribe);
console.assert(dog instanceof Genus);
console.assert(dog instanceof Species);

或者使用 new 运算符:

var cat = new Species('cat');
console.assert(cat instanceof Object);
console.assert(cat instanceof Family);
console.assert(cat instanceof Tribe);
console.assert(cat instanceof Genus);
console.assert(cat instanceof Species);

console.assert(Object.getPrototypeOf(dog) === Object.getPrototypeOf(cat))

我是否在实现过程中忽略了原型(prototype) OO 所需的功能?是否有我应该更改的 Javascript 约定或交互?总之,这里的“问题”是什么,是否有明显的改进之处?

我想成为构造函数定义的 DRYer,但我发现函数的名称属性不可写,而这正是支持 WebKit Inspector 的对象名称的原因。我能够构建一个 eval 来完成我想要的,但是......糟糕。

最佳答案

编辑:哦,我现在明白问题了。答:不,你完全正确。设置函数名称的唯一方法是在使用函数声明时,这意味着在评估时。因此,您需要在源代码中包含它(eval 是后门)。我之前回答了一个更简单的问题,但要点相同:Minor drawback with Crockford Prototypical Inheritance .关于此主题的另一个资源是 http://kangax.github.com/nfe/

有使用 displayName 属性的运动,以便将函数的不可更改的名称与其调试器外观分开。这是在 Firefox 和其他一些东西中实现的,并且是包含在 es6 中的稻草人,但目前还不是暂定规范的一部分:http://wiki.ecmascript.org/doku.php?id=strawman:name_property_of_functions

这是一篇来自一些在 Chrome 上工作的人关于命名函数主题的论文 http://querypoint-debugging.googlecode.com/files/NamingJSFunctions.pdf

这里是 chromium 问题,讨论了为什么它还没有实现:http://code.google.com/p/chromium/issues/detail?id=17356

进入原始答案:

您打算完成的事情,您已经很好地完成了。我做过的一些相似类型的例子:

首先是一个简单的“可继承”函数,它允许您执行以下操作:

var MyObjCtor = heritable({
constructor: function MyObj(){ /* ctor stuff */},
super: SomeCtor,
prop1: val,
prop2: val,
/**etc..*/
});


function heritable(definition){
var ctor = definition.constructor;
Object.defineProperty(ctor, 'super', {
value: definition.super,
configurable: true,
writable: true
});
ctor.prototype = Object.create(ctor.super.prototype);
delete definition.super;

Object.keys(definition).forEach(function(prop){
var desc = Object.getOwnPropertyDescriptor(definition, prop);
desc.enumerable = false;
Object.defineProperty(ctor.prototype, prop, desc);
});

function construct(){
var obj = new (ctor.bind.apply(ctor, [].concat.apply([null], arguments)));
ctor.super.call(obj);
return obj;
}

construct.prototype = ctor.prototype;

return construct;
}

另一个是创建用于 libffi (node-ffi) 的结构。本质上,您同时拥有构造函数继承和原型(prototype)继承。您创建的构造函数继承自构造函数,后者创建结构的实例。 https://github.com/Benvie/node-ffi-tools/blob/master/lib/Struct.js

为了创建一个命名函数,需要使用 eval,所以如果您需要一个命名构造函数,那就是这样。我毫不犹豫地在需要的地方使用它。

关于javascript - 带有 Object.create 和命名构造函数的原型(prototype) OO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9491300/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com