gpt4 book ai didi

javascript - 我如何做 JavaScript 原型(prototype)继承(原型(prototype)链)

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

这是 JavaScript 大师的问题。我正在尝试更优雅地使用 JavaScript 原型(prototype)模型。这是我的实用程序代码(它提供了真实的原型(prototype)链并正确使用 instanceof 运算符):

function Class(conf) {
var init = conf.init || function () {};
delete conf.init;

var parent = conf.parent || function () {};
delete conf.parent;

var F = function () {};
F.prototype = parent.prototype;
var f = new F();
for (var fn in conf) f[fn] = conf[fn];
init.prototype = f;

return init;
};

它允许我做这样的事:

var Class_1 = new Class({
init: function (msg) { // constructor
this.msg = msg;
},

method_1: function () {
alert(this.msg + ' in Class_1::method_1');
},

method_2: function () {
alert(this.msg + ' in Class_1::method_2');
}
});

var Class_2 = new Class({
parent: Class_1,

init: function (msg) { // constructor
this.msg = msg;
},

// method_1 will be taken from Class_1

method_2: function () { // this method will overwrite the original one
alert(this.msg + ' in Class_2::method_2');
},

method_3: function () { // just new method
alert(this.msg + ' in Class_2::method_3');
}
});

var c1 = new Class_1('msg');
c1.method_1(); // msg in Class_1::method_1
c1.method_2(); // msg in Class_1::method_2

var c2 = new Class_2('msg');
c2.method_1(); // msg in Class_1::method_1
c2.method_2(); // msg in Class_2::method_2
c2.method_3(); // msg in Class_2::method_3

alert('c1 < Class_1 - ' + (c1 instanceof Class_1 ? 'true' : 'false')); // true
alert('c1 < Class_2 - ' + (c1 instanceof Class_2 ? 'true' : 'false')); // false

alert('c2 < Class_1 - ' + (c2 instanceof Class_1 ? 'true' : 'false')); // true
alert('c2 < Class_2 - ' + (c2 instanceof Class_2 ? 'true' : 'false')); // true

我的问题是:有没有更简单的方法来做到这一点?

最佳答案

是的,有更好的方法来做到这一点。

var call = Function.prototype.call;

var classes = createStorage(),
namespaces = createStorage(),
instances = createStorage(createStorage);


function createStorage(creator){
var storage = new WeakMap;
creator = typeof creator === 'function' ? creator : Object.create.bind(null, null, {});
return function store(o, v){
if (v) {
storage.set(o, v);
} else {
v = storage.get(o);
if (!v) {
storage.set(o, v = creator(o));
}
}
return v;
};
}

function Type(){
var self = function(){}
self.__proto__ = Type.prototype;
return self;
}

Type.prototype = Object.create(Function, {
constructor: { value: Type,
writable: true,
configurable: true },
subclass: { value: function subclass(scope){ return new Class(this, scope) },
configurable: true,
writable: true }
});

function Class(Super, scope){
if (!scope) {
scope = Super;
Super = new Type;
}

if (typeof Super !== 'function') {
throw new TypeError('Superconstructor must be a function');
} else if (typeof scope !== 'function') {
throw new TypeError('A scope function was not provided');
}

this.super = Super;
this.scope = scope;

return this.instantiate();
}

Class.unwrap = function unwrap(Ctor){
return classes(Ctor);
};

Class.prototype.instantiate = function instantiate(){
function super_(){
var name = super_.caller === Ctor ? 'constructor' : super_.caller.name;
var method = Super.prototype[name];

if (typeof method !== 'function') {
throw new Error('Attempted to call non-existent supermethod');
}

return call.apply(method, arguments);
}

var Super = this.super,
namespace = namespaces(Super),
private = instances(namespace)

var Ctor = this.scope.call(namespace, private, super_);
Ctor.__proto__ = Super;
Ctor.prototype.__proto__ = Super.prototype;
namespaces(Ctor, namespace);
classes(Ctor, this);
return Ctor;
}

示例用法:

var Primary = new Class(function(_, super_){
var namespace = this;
namespace.instances = 0;

function Primary(name, secret){
this.name = name;
_(this).secret = secret;
namespace.instances++;
}

Primary.prototype.logSecret = function logSecret(label){
label = label || 'secret';
console.log(label + ': ' + _(this).secret);
}

return Primary;
});


var Derived = Primary.subclass(function(_, super_){

function Derived(name, secret, size){
super_(this, name, secret);
this.size = size;
}

Derived.prototype.logSecret = function logSecret(){
super_(this, 'derived secret');
}

Derived.prototype.exposeSecret = function exposeSecret(){
return _(this).secret;
}

return Derived;
});

var Bob = new Derived('Bob', 'is dumb', 20);
Bob.logSecret();
console.log(Bob);
console.log(Bob.exposeSecret());

关于javascript - 我如何做 JavaScript 原型(prototype)继承(原型(prototype)链),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11770992/

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