在两个相似的函数中重载__proto__之间的区别

时间:2012-09-26 15:50:06

标签: javascript

在我对制作类似数组对象的调查中,我做了这个函数,

Array2 = function(){
    var out = [];
    Object.defineProperty(out, 'prototype', { value : Array2.prototype }); // store a reference
    out.__proto__ = Array2.prototype; // necessary as Array uses __proto__ and not prototype

    if(arguments.length > 1) Array.prototype.push.apply(out, arguments);   // re-implement constructor's
    else if(arguments.length === 1) out.length = arguments[0];             // argument handling behaviour

    return out;
};

// allow for normal prototyping behaviour
Array2.prototype = [];
Object.defineProperty(Array2.prototype, 'constructor', { value : Array2 });

并注意到调用Array2()的返回方式与调用new Array2()相同,这不是我期望的,所以我考虑了一个类似的整数函数

Int = function(n){
    var out = ~~n;
    out.prototype = Int.prototype;
    out.__proto__ = Int.prototype;

    this.value = out; // added to check value when working as object

    return out;
};

Int.prototype = 0;
Int.prototype.constructor = Int;

这次,Int返回数字的正常实例(__proto__prototype,与任何数字文字一样),new Int返回带有{的{Int“对象{1}}为Empty__proto__undefinedprototype可提供号码,与不使用.value的号码相同。

为什么这些非常相似的函数的行为如此不同,为什么new导致第一个?很可能是我忽略了一些明显的东西 仅在Google Chrome中测试过。

1 个答案:

答案 0 :(得分:1)

实际上,您的Array2函数返回真正的数组,而不仅仅是类似数组的对象,这在将[[prototype]]设置为{0}时不会改变继承自Array.prototype的对象(尽管您不应该使用[]创建数组,但使用Object.create(Array.prototype)创建一个普通对象。

您的功能Int有几个问题。

out是原始数字值,没有属性。在分配一些时,它将被隐式地转换为Number对象,该对象将在之后被丢弃。 Int.prototype = 0上的“构造函数”属性存在同样的问题。

此外,您不能使用0之类的原始值作为原型对象。创建new Int实例时,它将从默认Object.prototype继承,因为0不是“对象”类型。我不确定在将此类属性分配给非标准__proto__属性时会发生什么,但我想它只是失败了。

请改用:

function Int(n){
    var out = ~~n;
    this.valueOf = function(){ return out; };
    return out; // when not used as a constructor, return int-casted number
};

Int.prototype = Object.create(Number.prototype, {
    constructor:{value:Int}
});