gpt4 book ai didi

javascript - 如何最好地从原生 JavaScript 对象继承? (尤其是字符串)

转载 作者:行者123 更新时间:2023-12-03 13:31:57 25 4
gpt4 key购买 nike

我是一个长期浏览者,但第一次参与。如果我遗漏了任何礼仪细节,请告诉我!

此外,我已经搜索了高低,包括这个网站,但我还没有找到关于我想要做什么的清晰简洁的解释。如果我错过了,请指出正确的方向!

好的,我想扩展一些原生 JavaScript 对象,例如 Array 和 String。但是,我不想实际扩展它们,而是创建从它们继承的新对象,然后修改它们。

对于数组,这有效:

var myArray = function (n){
this.push(n);

this.a = function (){
alert(this[0]);
};
}

myArray.prototype = Array.prototype;

var x = new myArray("foo");
x.a();

但是,对于 String,同样不起作用:
var myString = function (n){
this = n;

this.a = function (){
alert(this);
};
}

myString.prototype = String.prototype;

var x = new myString("foo");
x.a();

我也试过:
myString.prototype = new String();

现在,在尝试对此进行研究时,我发现这确实有效:
var myString = function (n){
var s = new String(n);

s.a = function (){
alert(this);
};

return s;
}

var x = myString("foo");
x.a();

然而,这对我来说几乎感觉像是“作弊”。就像,我应该使用“真正的”继承模型,而不是这个捷径。

所以,我的问题:

1)你能告诉我关于从String继承我做错了什么吗? (最好有一个工作示例......)

2)在“真正的”继承示例和“快捷方式”示例之间,您能说出一种方式相对于另一种方式的任何明显的好处或坏处吗?或者也许只是在一个功能上如何操作另一个方面的一些差异? (因为它们在我看来最终是一样的......)

谢谢大家!

编辑:

感谢所有评论/回答的人。我认为@CMS 的信息是最好的,因为:

1)他回答了我的字符串继承问题,指出通过在我自己的字符串对象中部分重新定义一个字符串,我可以使它工作。 (例如覆盖 toString 和 toValue)
2) 创建一个继承自 Array.

从以上两件事,我得出结论,JavaScript 的可继承性声明仅适用于您自己创建的对象,并且当涉及到 native 对象时,整个模型就会崩溃。 (这可能就是为什么您找到的 90% 的示例是 Pet->Dog 或 Human->Student,而不是 String->SuperString)。 @chjj 的回答可以解释这些对象实际上是原始值,即使 JS 中的所有内容似乎都是一个对象,因此应该是 100% 可继承的。

如果这个结论完全错误,请纠正我。如果它是准确的,那么我相信这对除了我自己以外的任何人来说都不是新闻——但再次感谢大家的评论。我想我现在有一个选择:

要么继续使用寄生继承(我现在知道名称的第二个例子),并尽可能减少它对内存使用的影响,要么做类似@davin、@Jeff 或 @chjj 建议的事情,要么 psudo-redefine 要么完全为自己重新定义这些对象(这似乎是一种浪费)。

@CMS - 将您的信息编译成答案,我会选择它。

最佳答案

这样做的痛苦简单但有缺陷的方法是:

var MyString = function() {};

MyString.prototype = new String();

您要求的内容很奇怪,因为通常在 JS 中,您不会将它们视为字符串对象,而是将它们视为“字符串”类型,即原始值。此外,字符串根本不可变。您可以通过指定 .toString 让任何对象像字符串一样工作。方法:
var obj = {};
obj.toString = function() {
return this.value;
};
obj.value = 'hello';

console.log(obj + ' world!');

但显然它不会有任何字符串方法。您可以通过几种方式进行继承。其中之一是javascript应该使用的“原始”方法,您和我在上面发布了该方法,或者:
var MyString = function() {};
var fn = function() {};
fn.prototype = String.prototype;
MyString.prototype = new fn();

这允许在不调用构造函数的情况下添加到原型(prototype)链。

ES5 的方式是:
MyString.prototype = Object.create(String.prototype, {
constructor: { value: MyString }
});

非标准但最方便的方法是:
MyString.prototype.__proto__ = String.prototype;

所以,最后,你可以做的是:
var MyString = function(str) {
this._value = str;
};

// non-standard, this is just an example
MyString.prototype.__proto__ = String.prototype;

MyString.prototype.toString = function() {
return this._value;
};

继承的字符串方法可能使用该方法工作,我不确定。我认为他们可能是因为有一个 toString 方法。这取决于任何特定的 JS 引擎如何在内部实现它们。但他们可能不会。你必须简单地定义你自己的。再一次,你所要求的很奇怪。

您也可以尝试直接调用父构造函数:
var MyString = function(str) {
String.call(this, str);
};

MyString.prototype.__proto__ = String.prototype;

但这也有点粗略。

无论你试图用这个做什么可能都不值得。我敢打赌,无论您尝试将其用于什么,都有更好的方法。

如果您想要 绝对可靠的方法:
// warning, not backwardly compatible with non-ES5 engines

var MyString = function(str) {
this._value = str;
};

Object.getOwnPropertyNames(String.prototype).forEach(function(key) {
var func = String.prototype[key];
MyString.prototype[key] = function() {
return func.apply(this._value, arguments);
};
});

这将在 this._value 上进行。到每个 String 方法。这会很有趣,因为你的字符串是可变的,不像真正的 javascript 字符串。

你可以这样做:
    return this._value = func.apply(this._value, arguments);

这将增加一个有趣的动态。如果您希望它返回您的字符串之一而不是 native 字符串:
    return new MyString(func.apply(this._value, arguments));

或者简单地说:
    this._value = func.apply(this._value, arguments);
return this;

根据您想要的行为,有几种方法可以解决它。

此外,您的字符串不会像 javascript 字符串那样具有长度或索引,解决此问题的一种方法是放入构造函数:
var MyString = function(str) {
this._value = str;
this.length = str.length;
// very rough to instantiate
for (var i = 0, l = str.length; i < l; i++) {
this[i] = str[i];
}
};

非常hacky。根据实现,您可能只能调用那里的构造函数来添加索引和长度。如果你想使用 ES5,你也可以使用 getter 作为长度。

尽管如此,你想在这里做的事情无论如何都不理想。这将是缓慢且不必要的。

关于javascript - 如何最好地从原生 JavaScript 对象继承? (尤其是字符串),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6804370/

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