javascript继承是危险的

时间:2015-07-21 11:49:39

标签: javascript node.js inheritance

我们如何防止下面代码中的危险行为?

var ee = require('events').EventEmitter;
var util = require("util");

util.inherits(strr, ee);

function strr() {
  ee.call(this);
  this._events = 0;  // modify the private member value in parent
}

如果您不知道this._events是父EventEmitter对象中的私有变量成员,那么内部数据会自行破坏(变异) (继承课程)。 但我们无法了解有关父私人成员的所有信息。

上面的代码使用node.js而不是那么容易理解问题。 我再添加一些

function Parent() {
  this.x = 0;
  this.y = 0;
  this._secre = 1;
}

Parent.prototype.run = function(x, y) {
  if (this._secre) {
    console.log('run');
  }
};

function Child() {
  Parent.call(this); // call super constructor.
  this._secret = 0; //accidently make the same member name with the parent
}

// subclass extends superclass
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

Child.prototype.show = function() {
  this.run();
  console.log("Show my secret -> %s", this._secret);
};

var child = new Child();

console.log('Is child an instance of Child? ' + (child instanceof Child)); // true
console.log('Is child an instance of Parent? ' + (child instanceof Parent)); // true
child.show(); 

将输出

Is child an instance of Child? true
Is child an instance of Parent? true
run
Show my secret -> 0

但如果你意外地用_secret命名孩子的_secre成员,那么你就不会得到“运行输出”

function Parent() {
  this.x = 0;
  this.y = 0;
  this._secre = 1;
}

Parent.prototype.run = function(x, y) {
  if (this._secre) {
    console.log('run');
  }
};

function Child() {
  Parent.call(this); // call super constructor.
  this._secre = 0; //accidently make the same member name with the parent
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

Child.prototype.show = function() {
  this.run();
  console.log("Show my secret -> %s", this._secre);
};

var child = new Child();

console.log('Is child an instance of Child? ' + (child instanceof Child)); // true
console.log('Is child an instance of Parent? ' + (child instanceof Parent)); // true
child.show(); 

3 个答案:

答案 0 :(得分:1)

不,阻止外部脚本访问“私有”变量的唯一方法是将该私有变量作用于函数内:

;(function() {
    var private_var;
)());

如果对象的属性要在对象内部使用,但不打算在对象外部访问,则通常使用下划线前缀命名约定。

obj._private

但实际上阻止其他开发人员访问此类属性(如果他们有权访问其父对象)并且可能更改其值。

答案 1 :(得分:0)

有更好的方法来继承EventEmitter

name  String
description String
usersArray  Array of json objects like:   [{"id": "123"}, {"id": "456}]
imgIcon  Png/Image    providing  /path/to/imageIcon.png
imgHeader Png/Image     providing /path/to/imageHeader.png

答案 2 :(得分:0)

  

如果您不知道this._events是父EventEmitter对象中的私有变量成员,

不,它不是私密的。如果您不相信,请查看EventEmitter的来源。

也就是说,Eve​​ntEmitter是一个有趣的例子,说明如何在JavaScript中管理状态,值得研究。

我们还能说什么? JavaScript不是Java。 :P