English 中文(简体)
javascript中的递归原型继承?
原标题:Recursive prototypal inheritance in javascript?
Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};

来自JavaScript中的原型继承

我已经使用此代码创建从以前的对象继承的新对象有一段时间了。然而,我遇到了一个小惊喜。

a = {
    foo: [1,2,3]
}

b = Object.create(a);
// b.foo -> [1,2,3]
b.foo = "test";
// b.foo -> "test"
// a.foo -> [1,2,3]

c = Object.create(a);
// c.foo -> [1,2,3]
c.foo[0] =  test ;
// c.foo -> ["test",2,3]
// a.foo -> ["test",2,3]

在尝试更改c.foo时,我更改了a.foo,而c.foo显示了更改,因为它继承了。我现在看到的唯一解决方案是只修改b的直接属性:

d = Object.create(a);
d.foo = Object.create(a.foo);
d.foo[0] =  text ;

我确信我缺少一个更好的解决方案如何在不冒修改原始对象的风险的情况下从旧对象创建新对象

问题回答

+1用于引用Crockford=D

我认为数组总是通过引用传递的,并且数组永远不会被复制。我想Array.slice会复制它,但那是一个边缘案例。。。

create函数主要用于复制函数等。我从来没有使用过这个方法,因为我只是创建了一个构造函数:

function a() {
    this.foo = [0, 1, 2];
}

这样,每次调用都会得到一个新数组。只需执行b=new a();它对我有用。。。

我尽量避免继承,因为它总是有问题。我只会使用构造函数,然后为它分配新的变量(而不是原型)。然而,多重继承变得很棘手。。。

从原型创建新对象时,不会进行复制。甚至没有复制属性:

function F() {}
F.prototype.a = 1
new F().hasOwnProperty("a") // => false
new F().a // => 1

如果你这样做

var f = new F();
f.a = 2;

然后,您没有更改F.中的属性。原型,您正在向F添加一个新属性:

var f = new F();
f.a = 2;
f.a // => 2;
delete f.a;
f.a // => 1

因此,这适用于您分配属性的每个值。如果你想克隆一个值,你必须显式地克隆,最简单的方法就是在构造函数中设置一个新属性:

function F() {
  this.a = [];
}
var f = new F();
var g = new F();
f.a === g.a // => false

只有当原型包含可变值,其他值无法修改(属性可以更改值)时,才会出现此问题。

如果你想“子类”F,记得从新的构造函数中调用它:

function F() { this.a = []; }
function G() { F.call(this); }
G.prototype = new F();

我见过的最好的继承模式是GoogleClosureLibrary的继承模式。它基于构造函数。以下是示例:

//with this method we will inherit one "class" (there are no real classes in JS) from another.
var inherit = function (c, p) {
    function F() {}
    F.prototype = p.prototype;
    c.prototype = new F;
    c.prototype.constructor = c;
};

//create one "class"
var A = function(){
    this.foo = [1,2,3];
}
//create its instance
var a = new A();

//create another "class"
var C = function(){
    //call the parent constructor
    A.call(this);
}
//make inheritance
inherit(C, A);
//create example of inherited "class"
var c = new C();

结果如你所愿:

console.log(c.foo);
//-> [1,2,3]
c.foo[0] =  test ;
console.log(c.foo);
//-> [ test ,2,3]
console.log(a.foo);
//-> [1,2,3]

嗯,是的:

1)

b.foo = "test";
// b.foo -> "test"

将你的F.prototype引用的a替换为“test”,这样你就不会看到错误,但实际上这比2)

2)

c = Object.create(a);
// c.foo -> [1,2,3]
c.foo[0] =  test ;
// c.foo -> ["test",2,3]
// a.foo -> ["test",2,3]

修改自c.foo[0]以来的a对象&;a.foo指向它(它们是指向a值的引用/指针)

解决方案此处

这就是解决方案:


Object.create = function (o) {
    function F() {
        for(var prop in this)
            if(o.hasOwnProperty(prop))
                this[prop] = Object.create(o[prop]);
    }
    F.prototype = o;
    return new F();
};

这个解决方案的一般限制是原型不应该有递归引用。

也有可能在没有限制的情况下解决这个问题,但解决方案会更复杂。为了防止无限递归对象的创建,您可以在初始化过程中使用某种临时映射存储。此存储将是初始化对象之间的缓存引用。





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签