在对象类声明中设置javascript原型函数 [英] Setting javascript prototype function within object class declaration

查看:92
本文介绍了在对象类声明中设置javascript原型函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,我见过在类定义之外声明的原型函数,如下所示:

Normally, I've seen prototype functions declared outside the class definition, like this:

function Container(param) {
    this.member = param;
}
Container.prototype.stamp = function (string) {
    return this.member + string;
}

var container1 = new Container('A');
alert(container1.member);
alert(container1.stamp('X'));

此代码生成两个值为A和AX的警报。

This code produces two alerts with the values "A" and "AX".

我想定义类定义的原型函数INSIDE。做这样的事情有什么不妥吗?

I'd like to define the prototype function INSIDE of the class definition. Is there anything wrong with doing something like this?

function Container(param) {
    this.member = param;
    if (!Container.prototype.stamp) {
        Container.prototype.stamp = function() {
            return this.member + string;
        }
    }
}

我正在尝试这样做我可以访问类中的私有变量。但是我发现如果我的原型函数引用了私有var,那么private var的值总是初始化函数初始化时使用的值,而不是对象实例中的值:

I was trying this so that I could access a private variable in the class. But I've discovered that if my prototype function references a private var, the value of the private var is always the value that was used when the prototype function was INITIALLY created, not the value in the object instance:

Container = function(param) {
    this.member = param;
    var privateVar = param;
    if (!Container.prototype.stamp) {
        Container.prototype.stamp = function(string) {
            return privateVar + this.member + string;
        }
    }
}
var container1 = new Container('A');
var container2 = new Container('B');
alert(container1.stamp('X'));
alert(container2.stamp('X'));

此代码生成两个值为AAX和ABX的警报。我希望输出为AAX和BBX。我很好奇为什么这不起作用,如果有其他模式我可以使用。

This code produces two alerts with the values "AAX" and "ABX". I was hoping the output would be "AAX" and "BBX". I'm curious why this doesn't work, and if there is some other pattern that I could use instead.

编辑:请注意我完全理解,对于这个简单的例子,最好只使用像 this.stamp = function(){} 这样的闭包,而根本不使用原型。我就是这样做的。但我正在尝试使用原型来了解更多相关内容,并希望了解一些事情:

Note that I fully understand that for this simple example it would be best to just use a closure like this.stamp = function() {} and not use prototype at all. That's how I would do it too. But I was experimenting with using prototype to learn more about it and would like to know a few things:


  • 什么时候使用才有意义原型功能而不是闭包?我只需要使用它们来扩展现有的对象,比如 Date 。我已经读过闭包更快

  • 如果由于某种原因我需要使用原型函数,在类中定义它是否OK,就像在我的例子中一样,或者应该它是在外面定义的吗?

  • 我想理解为什么原型函数无法访问每个实例的privateVar值,只有第一个实例的值。

  • When does it make sense to use prototype functions instead of closures? I've only needed to use them to extend existing objects, like Date. I've read that closures are faster.
  • If I need to use a prototype function for some reason, is it "OK" to define it INSIDE the class, like in my example, or should it be defined outside?
  • I'd like to understand why the privateVar value of each instance is not accessible to the prototype function, only the first instance's value.

推荐答案


什么时候使用原型函数而不是闭包?

When does it make sense to use prototype functions instead of closures?

嗯,这是最轻量级的方式,假设你在原型中有一个方法某个构造函数,并且您创建了1000个对象实例,所有这些对象都将在您的原型链中包含您的方法,并且所有这些对象仅引用一个函数对象

Well, it's the most lightweight way to go, let's say you have a method in the prototype of certain constructor, and you create 1000 object instances, all those objects will have your method in their prototype chain, and all of them will refer to only one function object.

如果在构造函数中初始化该方法,例如( this.method = function(){}; ),所有1000个对象实例都将函数对象作为自己的属性。

If you initialize that method inside the constructor, e.g. (this.method = function () {};), all of your 1000 object instances will have a function object as own property.


如果我出于某种原因需要使用原型函数,在类中定义它是否OK,就像在我的例子中一样,还是应该在外面定义? / p>

If I need to use a prototype function for some reason, is it "OK" to define it INSIDE the class, like in my example, or should it be defined outside?

在内部定义构造函数原型的成员,没有多大意义,我会向你详细解释它,为什么你的代码不起作用。

Defining the members of a constructor's prototype inside itself, doesn't makes much sense, I'll explain you more about it and why your code doesn't works.


我想了解为什么原型函数无法访问每个实例的privateVar值,第一个实例的值。

I'd like to understand why the privateVar value of each instance is not accessible to the prototype function, only the first instance's value.

让我们看看你的代码:

var Container = function(param) {
    this.member = param;
    var privateVar = param;
    if (!Container.prototype.stamp) {  // <-- executed on the first call only
        Container.prototype.stamp = function(string) {
            return privateVar + this.member + string;
        }
    }
}

关于代码的关键点行为是在第一次方法调用时创建 Container.prototype.stamp 函数

The key point about your code behavior is that the Container.prototype.stamp function is created on the first method invocation.

在您创建函数对象时,它会将当前封闭范围存储在名为 [[Scope]] 的内部属性中。

At the moment you create a function object, it stores the current enclosing scope in an internal property called [[Scope]].

当您通过使用 var 或FunctionDeclaration在其中声明的标识符(变量)调用函数时,稍后会扩充此作用域。

This scope is later augmented when you call the function, by the identifiers (variables) declared within it using var or a FunctionDeclaration.

[[Scope]] 属性列表构成范围链,当您访问标识符(如 privateVar 变量),检查这些对象。

A list of [[Scope]] properties forms the scope chain, and when you access an identifier (like your privateVar variable), those objects are examined.

并且因为你的函数是在第一个创建的方法调用( new Container('A')), privateVar 绑定到第一个函数调用的Scope,无论你如何,它都将继续受其约束调用方法。

And since your function was created on the first method invocation (new Container('A')), privateVar is bound to the Scope of this first function call, and it will remain bound to it no matter how do you call the method.

看看这个回答,第一部分是关于 with 声明,但在第二部分,我将讨论范围链如何为函数工作。

Give a look to this answer, the first part is about the with statement, but in the second part I talk about how the scope chain works for functions.

这篇关于在对象类声明中设置javascript原型函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆