JavaScript:何时在构造函数内定义函数,何时使用原型?

9

我正在学习Javascript,并有几个关于Javascript和面向对象编程的问题。我注意到在各种教程中,“类”中函数的声明方式不同。首先是在构造函数内部:

Class = function () {
  this.doSomething = function() {....};
}

另外一个是:
Class = function () {}
Class.prototype.doSomething  = function() {....};

在什么情况下应该使用第一种结构,在什么情况下应该使用第二种结构?
另一个问题是:我是否正确理解了js中没有“protected”属性或方法?应该使用什么代替?
提前感谢!

3
关于你的第二个问题(实际上应该是一个单独的问题):在方法前面加下划线。人们会知道这些是通常不应被访问的内部方法。 - ThiefMaster
1个回答

14

当你在构造函数内部定义一个函数,如this.myFunction=...,它只属于当前实例。这意味着它必须为所有实例构造并保存在内存中,这可能会很耗费资源,并且它也不能被继承。

唯一有效的理由是:

  • 封装特定的值
  • 其他类型的特定函数(每次可能构建不同的函数)

通常,你真正需要的是在原型上定义的函数。

根据MDN关于对象的文档

JavaScript中的所有对象都是Object的后代;所有对象都继承自Object.prototype的方法和属性,尽管它们可能被覆盖。例如,其他构造函数的原型会覆盖构造函数属性并提供它们自己的toString方法。对Object原型对象的更改会传播到所有对象,除非受这些更改影响的属性和方法沿原型链进一步被覆盖。

关于你的附加问题:以下代码构建了一个不直接可访问的函数:

Class = function () {
   var imprivate = function(){...};
   this.doSomething = function() { uses imprivate};
}

一个缺点是您对于Class的每个实例都有一个不同的函数实例。这通常用于模块(只有一个实例)。就个人而言,我更喜欢像ThiefMaster在评论中建议的那样:使用_为我的私有函数添加前缀:

// private method
XBasedGrapher.prototype._ensureInit = function() {

感谢您的出色回答! - Eugeny89
那么私有方法(我的意思是var imprivate = function(){...};)最好只在没有太多实例的类中使用? - Eugeny89
你可以这么说。个人而言,我认为没有必要对抗其他程序员,所以我只是使用“_”符号(附带一个“//私有方法”注释),这对我的同事来说已经足够清晰了。 - Denys Séguret

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接