在构造函数内部*分配原型方法-为什么不呢?

詹姆斯·赫斯顿

从风格上讲,我更喜欢这种结构:

var Filter = function( category, value ){
  this.category = category;
  this.value = value;

  // product is a JSON object
  Filter.prototype.checkProduct = function( product ){
    // run some checks
    return is_match;
  }

};

为此结构:

var Filter = function( category, value ){
  this.category = category;
  this.value = value;
};// var Filter = function(){...}

Filter.prototype.checkProduct = function( product ){
  // run some checks
  return is_match;
}

从功能上讲,以这种方式构造代码是否有任何弊端?将原型方法添加到构造函数内部的原型对象中(即,在构造函数的表达式语句关闭之前)会导致意外的作用域问题吗?

在成功使用之前,我已经使用了第一种结构,但是我想确保自己不会因为调试错误而使自己陷入麻烦,也不会引起开发人员的同情和痛苦。

jfriend00

从功能上讲,以这种方式构造代码是否有任何弊端?将原型方法添加到构造函数内部的原型对象中(即,在构造函数的表达式语句关闭之前)会导致意外的作用域问题吗?

是的,存在缺陷和意外的范围界定问题。

  1. 一遍又一遍地将原型分配给本地定义的函数,都将重复该分配并每次都创建一个新的函数对象。由于不再引用早期的分配,因此将对其进行垃圾回收,但是与第二个代码块相比,在构造函数的运行时执行和垃圾回收方面,这都是不必要的工作。

  2. 在某些情况下会出现意外的范围问题。有关Counter明确示例,请参见答案末尾的示例。如果从原型方法中引用构造函数的局部变量,则第一个示例将在代码中创建潜在的讨厌的错误。

还有一些其他(较小的)差异。您的第一个方案禁止在构造函数外部使用原型,如下所示:

Filter.prototype.checkProduct.apply(someFilterLikeObject, ...)

而且,当然,如果有人使用过:

Object.create(Filter.prototype) 

如果不运行Filter构造函数,那还会产生不同的结果,可能不太可能,因为可以合理地预期使用Filter原型的某些东西应该运行Filter构造函数才能达到预期的结果。


从运行时性能的角度(对象上调用方法的性能)来看,这样做会更好:

var Filter = function( category, value ){
  this.category = category;
  this.value = value;

  // product is a JSON object
  this.checkProduct = function( product ){
    // run some checks
    return is_match;
  }

};

有一些Javascript“专家”声称不再需要使用原型节省内存(我几天前看了一个视频讲座),是时候开始在对象上直接使用性能更好的方法了,比原型 我不知道我是否准备倡导自己,但这是值得考虑的有趣问题。


我能想到的第一种方法的最大缺点是,犯一个讨厌的编程错误真的非常容易。如果您碰巧认为可以利用原型方法现在可以看到构造函数的局部变量这一事实,那么当您拥有一个以上的对象实例时,您将很快陷入困境。想象一下这种情况:

var Counter = function(initialValue){
  var value = initialValue;

  // product is a JSON object
  Counter.prototype.get = function() {
      return value++;
  }

};

var c1 = new Counter(0);
var c2 = new Counter(10);
console.log(c1.get());    // outputs 10, should output 0

问题的演示:http : //jsfiddle.net/jfriend00/c7natr3d/

这是因为,虽然该get方法看起来像一个闭包,并且可以访问作为构造函数的局部变量的实例变量,但实际上它并不起作用。由于所有实例共享同一个原型对象,因此该Counter对象的每个新实例都会创建该get函数的新实例(可以访问刚刚创建的实例的构造函数局部变量)并将其分配给原型,因此现在所有实例都具有一个get访问最后创建的实例的构造函数的局部变量的方法。这是一场编程灾难,因为这可能永远都不是原本打算的,并且很容易成为弄清问题出在哪里以及为什么原因的抓手。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

人们为什么不建议在Servlet / SIP Servlet上使用构造函数呢?

无法直接调用超类型构造函数-为什么不呢?

在构造函数中初始化变量后进行验证:为什么不这样做呢?

如果不继承构造函数,为什么会调用它们呢?

为什么gcc5.4不编译调用非constexpr函数的constexpr函数,而icpc编译呢?

F#中是否有函数专业化,为什么不呢?

char argv [] []作为主要函数参数,为什么不呢?

带有DATE和COLUMN函数的SUM PRODUCT不起作用-为什么不呢?

Vue更改文档不鼓励使用的数据的方法-但是为什么呢?

具有@Value注释和单个方法的字段。我应该让它们都静止吗?为什么/为什么不呢?

为什么不应该通过原型向JavaScript构造函数添加功能呢?

JavaScript中的原型有什么意义?为什么不直接将方法添加到构造函数?

为什么是Java构造函数呢?变量没有分配给数组?

关于Redux-thunk,如果处理程序调度了要调用的函数,为什么不直接调用它呢?

为什么不“使”回声呢?

在C ++中声明const对象需要用户定义的默认构造函数。如果我有一个可变的成员变量,为什么不呢?

为什么不构造内部类?C ++

为什么可以将构造函数原型分配给对象及其含义

为什么需要设置原型构造函数?

关于Java中的Singleton模式,为什么不直接将静态变量分配给方法中的新局部变量,为什么不直接使用静态变量呢?

为什么@TupleConstructor不生成构造函数

Dlang:为什么不构造函数?

为什么不直接使用构造函数?

构造函数为什么不设置参数?

为什么要为函数本身分配函数原型的构造函数?Programmer.prototype.constructor =程序员

内存分配失败。但是为什么会崩溃?还是呢?

分配NSManagedObject时prepareForSegue崩溃,但是为什么呢?

为什么此语法会导致其属性构造函数指向其自身的构造函数呢?

为什么我可以在不声明C的情况下在C中调用函数,而在C ++中却不能呢?