2

基本上每个在 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);
}

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

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


所以这是我的困境。

您是否将原型继承与hasOwnProperty方法结合使用,但冒着在枚举过程中让成员离链太远的风险?

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

4

2 回答 2

3

嗯。您说的是“原型链中非常接近”,但实际上,非常接近是什么意思?三级深是“近”还是“远”。

无论如何,您可以更改一点 beget 函数并为每个对象实现自己的 hasOwnProperty 函数,该函数只会通过原型链直到对象级别。这将解决您通过不使用 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
于 2010-09-29T13:38:11.960 回答
0

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

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


直接向对象添加成员并不是真正的继承形式,除非您当然使用该begetObject()技术创建对象......因为它使用原型来添加成员。

于 2010-09-29T09:15:32.630 回答