我的困境涉及JavaScript的Prototypal Inheritance和hasOwnProperty方法

时间:2010-09-29 08:41:15

标签: javascript inheritance prototype hasownproperty

基本上每个人都在JavaScript中写关于成员枚举的人都大力提倡使用hasOwnProperty方法来避免上升原型链。

我知道这是防御性编程的一种形式,以防止迭代例如添加到Object.prototype的成员。但其他继承成员呢?比如,原型链中非常接近的成员......您实际上想要枚举的成员。

假设我有以下内容:

var beget = function (o) { // http://javascript.crockford.com/prototypal.html
    function F() {};
    F.prototype = o;
    return new F();
};

var john = { name: 'john', surname: 'grech' },
    mary = beget(john),
    p;

mary.age = 42; //augmenting 'mary'

// 'surname' in mary              => true
// mary.hasOwnProperty('surname') => false

for (p in mary) {
    //skipping over non-direct members, meaning that we also skip members
    //inherited from 'john'
    if (!mary.hasOwnProperty(p)) { 
        continue;
    }
    console.log(p);
}

在上面的示例中,只会显示age,因为agemary的唯一直接成员......其他两个成员namesurname,是原型链。

但显然,我希望在for..in构造中迭代所有3个成员;但如果您删除hasOwnProperty,则可以从Object.Prototype获取成员,如果有人添加了功能。


所以这就是我的困境。

您是否将原型继承与hasOwnProperty方法结合使用,但在枚举期间冒险让成员在链条上走得太远?

或者您是否使用其他形式的继承将直接添加到对象而不是原型?

2 个答案:

答案 0 :(得分:3)

嗯。你说“在原型链中非常接近”,但实际上,这意味着什么非常接近?是三级深度“接近”还是“远”。

无论如何,你可以改变一个beget函​​数并为每个对象实现自己的hasOwnProperty函数,它只会通过原型链直到Object级别。这将解决您通过不使用hasOwnProperty获取添加到Object.prototype的成员的困境。代码如下:

var beget = function (o) { // http://javascript.crockford.com/prototypal.html
    function F() {
        this.hasOwnProperty = function(key) {
            return (key != "hasOwnProperty" 
                && Object.prototype.hasOwnProperty.call( this, key ) 
                || o.hasOwnProperty( key )
            );
        }
    };

    F.prototype = o;
    return new F();
};

var john = { name: 'john', surname: 'grech' },
    mary = beget( john ),
    p    = beget( mary );

mary.age  = 42; //augmenting 'mary'
mary.name = "mary";
p.size    = "38";

// testing prototype of Object.
Object.prototype.not_own = function(){}

for(var i in p) {
    console.debug('Key',i, p.hasOwnProperty(i));
}

// p.hasOwnProperty("size");    // -> true
// p.hasOwnProperty("age");     // -> true
// p.hasOwnProperty("name");    // -> true
// p.hasOwnProperty("not_own"); // -> false

答案 1 :(得分:0)

如果您需要遍历对象的原型链,可以使用hasOwnProperty跳过直接成员(正如您所说)。这当然也会迭代添加到该对象原型中的任何其他成员(Object.Prototype等)。没有办法避免这种情况。

这就像询问如何避免枚举car = {yellow, green, black}对象的某些成员(伪代码)......你没有......你只是根据它们的价值跳过某些成员。


直接向对象添加 成员实际上并不是一种继承形式,除非您使用begetObject()技术创建对象...因为它使用Prototype添加成员