2015-07-21 3 views
0

Как мы можем предотвратить опасное поведение в коде ниже?Наследование javascript опасно

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 и не так просто понять проблему. добавить еще немного

Он будет выводить

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

Но если вы случайно имя члена _secre ребенка с _secret, то вы не получите «выход запуска»

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(); 
+0

очень опасно, что я не мог понять вопрос ... –

+0

_Cough cough_. Частный член? –

ответ

0

Есть лучшие способы унаследовать EventEmitter

Child.prototype.__proto__ = EventEmitter.prototype; 
Child.prototype = Object.create(EventEmitter.prototype) 
+0

Как вы сказали, на самом деле то же самое, что я сказал. node.js просто упакуйте свой код в util.inherits, а опасный код не находится в этой части. Это вызов родителя с этим. Он назначит ваш указатель родительской функцией init. – Naryc

1

Нет, единственный способ остановить внешний скрипт от доступа к «частной» переменной является объем, что частная переменная внутри функции:

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

В случае свойств объекта, которые предназначены для используемые внутри объекта, но не предназначены для доступа извне объекта, конвенция использует соглашение об именах префикса подчеркивания.

obj._private 

Но нет ничего на самом деле остановки другого разработчик доступа к такой собственности (если они имеют доступ к его родительскому объекту) и, возможно, изменяя его значение.

+0

Я знаю шаблон закрытия. Но это не реально наследуется в js, и большинство людей используют шаблон, который я указал выше. Так что это опасно errrrrr. – Naryc

0

Если вы не осведомлен this._events является частным переменным членом родительского объекта EventEmitter,

Нет, это не частное. Пойдите посмотреть источник для EventEmitter, если вы не уверены.

Сказанное, EventEmitter - интересный пример того, как управлять состоянием в JavaScript, стоит изучать.

Что еще мы можем сказать? JavaScript не является Java. : p

Смежные вопросы