3

在 John Resig 关于Javascript 中的简单“类”实例化的帖子中,他指出:

“...如果您有一个希望人们与之交互的经常访问的函数(返回一个对象),那么将对象属性放在原型链中并实例化它对您有利。这里是,在代码中:"

// Very fast
function User(){}
User.prototype = { /* Lots of properties ... */ };
// Very slow
function User(){
    return { /* Lots of properties */ };
}

我想将此应用于如下函数(恰好位于“类”声明中)

//...
this.get_subscription = function(args)
{
    return {
        property_one: "value",
        property_two: {
            sub_prop: args.something
        }
    }
}

但不知道将参数放在哪里。如果我做

this.get_subscription = function(args) {}
this.get_subscription.prototype = {
    property_one: "value"
    //...
}

它会说 args 是未定义的。我已经尝试了几种变体,但都不起作用。我应该如何正确地做到这一点,而不是将 args 放在父类的范围内?

4

2 回答 2

3

您似乎误解了prototype. 原型包含对象的所有实例应该通用的方法和字段。因此,如果property_two是基于args传递给构造函数的,那么它就不属于原型!

毕竟,在这段代码中

this.get_subscription = function(args) {}
this.get_subscription.prototype = {
    property_one: "value"
    //...
}

首先,get_subscription创建函数,然后将其原型设置为对象字面量。在调用构造函数之前是没有args的,所以args在原型中做一些事情是没有意义的。

所以,你常用的 javascript 对象应该看起来像这个例子 - 一个 2D 点类。

function Point(x, y) {
    /*  In constructor:
     *  initialize fields that are related to the constructor parameters
     *  and are different for different instances
     */
    this.x = x;
    this.y = y;
}

// in prototype, define fields that are  common to all instances
Point.prototype.RED = '#FF0000';

/*  in prototype, also define the methods; as they can use the "this" keyword,
 *  they can reference their own instance, so you don't have to include them
 *  in each instance manually
 */

Point.prototype.toString = function() { return '[' + this.x + ', ' + this.y + ']'; };
于 2012-05-02T23:32:48.937 回答
1

是的,这就是“一切到原型”理念的缺点:您无权访问构造函数参数——它们只能函数体内使用(除非您将它们放入那里的公共属性中)。所有需要用到它们的东西都不属于原型;您只会在原型上填写“默认属性”(通常是所有实例通用的方法)。

我认为你在这里无论如何都不需要那个。该模式仅对真正的构造函数有用,您在这里似乎没有(我会期望this.Subscription)。此外,承诺的“性能提升”可以忽略不计。

如果你真的想在这里使用它,它会是:

function Class() {
   this.Subscription = function(args) {
       this.propertyTwo = {
           subprop: args.something
       };
   };
   this.Subscription.prototype = {
       property_one: "value",
       property_two: {}
   };
}
// a method callable without the "new" operator:
Class.prototype.get_subscription = function(args) {
     return new this.Subscription(args);
}

用法:

var object = new Class();
var sub = new object.Subscription();
var sub2 = new object.Subscription();
// the promised boost is less memory usage for:
sub.propertyOne === object.Subscription.prototype.propertyOne === sub2.propertyOne;

还要注意Crockford 的原型继承 -当您尝试在propertyTwo-Object(s) 上设置/更改/删除属性时,嵌套对象的问题。

于 2012-05-02T23:34:31.417 回答