Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/424.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解决javascript继承中私有成员的潜在命名冲突_Javascript_Node.js_Oop - Fatal编程技术网

解决javascript继承中私有成员的潜在命名冲突

解决javascript继承中私有成员的潜在命名冲突,javascript,node.js,oop,Javascript,Node.js,Oop,这里我要问的问题不是如何在js对象上实现私有成员。 可以按如下方式进行 function MyClass(member){ var privateMember = member; this.getPrivateMember = function(){ return privateMember; }; } my = new MyClass("newbie"); console.log(my.getPrivateMember()); var util = r

这里我要问的问题不是如何在js对象上实现私有成员。 可以按如下方式进行

function MyClass(member){
    var privateMember = member;
    this.getPrivateMember = function(){
        return privateMember;
    };
}
my = new MyClass("newbie");
console.log(my.getPrivateMember());
var util = require("util");
var events = require("events");
var _ = require("underscore");

function MyStream() {
    events.EventEmitter.call(this);
    this.__MyStream = {
        _events: "",
        _maxListeners: 0
    }
}

util.inherits(MyStream, events.EventEmitter);

_.extend(MyStream.prototype, {
    write: function(data){
        this.__MyStream._events = "This will not override the super member but it's odd";
        this.emit("data", data);
    },

//    on: function(){
//        console.log("my on");
//        events.EventEmitter.prototype.on.apply(this, arguments);
//    },

    constructor: MyStream
});

var stream = new MyStream();

console.log(stream instanceof events.EventEmitter); // true
console.log(stream instanceof MyStream); // true

stream.on("data", function(data) {
    console.log('Received data: "' + data + '"');
})
stream.write("It works!"); // Received data: "It works!"
但问题是并不是所有的库都以闭包的形式实现它们的对象,而且它有性能问题,因为函数成员在每个实例中都是闭包,而不是只有一个副本的原型

请参阅上的示例代码

node.js作为util.inherits正式实现了inherit 我阅读了util和events的源代码。 util.inherits的代码是

exports.inherits = function(ctor, superCtor) {
    ctor.super_ = superCtor;
    ctor.prototype = Object.create(superCtor.prototype, {
        constructor: {
            value: ctor,
            enumerable: false,
            writable: true,
            configurable: true
        }
    });
};
你知道它只是把超级构造函数的原型作为子构造函数的原型,当然不会隐藏超级构造函数的私有成员。 当我们将subconstructor构造为示例代码时

function MyStream() {
    events.EventEmitter.call(this);
}
EventEmitter的所有成员都将放在MyStream实例中。 除非阅读events.EventEmitter的源代码,否则您不知道将得到什么。 为了简洁起见,我把它读了一遍,复制到这里

function EventEmitter() {
    this.domain = null;
    if (exports.usingDomains) {
        // if there is an active domain, then attach to it.
        domain = domain || require('domain');
        if (domain.active && !(this instanceof domain.Domain)) {
            this.domain = domain.active;
        }
    }
    this._events = this._events || {};
    this._maxListeners = this._maxListeners || defaultMaxListeners;
}
exports.EventEmitter = EventEmitter;
您知道许多js编码人员使用下划线前缀命名成员,因为它应该是私有的,最好不要被其他人修改。但这不是解决方案,因为您不知道带下划线前缀的成员是什么。如果使用下划线定义自己的伪私有成员,则超级伪私有成员可能与您的同名。你可能会摧毁superior的营地。 我模拟如下一种情况

var util = require("util");
var events = require("events");
var _ = require("underscore");

function MyStream() {
    events.EventEmitter.call(this);
    this._events = "";
}

util.inherits(MyStream, events.EventEmitter);

_.extend(MyStream.prototype, {
    write: function(data){
        this._events = "This will override the super member and undermine the events list";
        this.emit("data", data);
    },

//    on: function(){
//        console.log("my on");
//        events.EventEmitter.prototype.on.apply(this, arguments);
//    },

    constructor: MyStream
});

var stream = new MyStream();

console.log(stream instanceof events.EventEmitter); // true
console.log(stream instanceof MyStream); // true

stream.on("data", function(data) {
    console.log('Received data: "' + data + '"');
})
stream.write("It works!"); // Received data: "It works!"
执行代码,它将不会输出收到的数据:“它工作!”除非您对此行进行注释。\u events=“这将覆盖超级成员并破坏事件列表”

有一段时间,我自己认为解决方案只能解决这个问题,也许我可以使用python中使用的模式。 如果您得到一个名为YourClass的类的成员,其前缀为uuuuuu,就像python中的uuuu yourMember一样,python编译器会将名称更改为uuu Classname u yourMember。所有私有成员都将以_Classname作为前缀。如果类名是唯一的,那么您的私有成员也将是唯一的。 Javascript没有python那样的编译机制,所以我应该自己定义它。 将前一代码更改如下

function MyClass(member){
    var privateMember = member;
    this.getPrivateMember = function(){
        return privateMember;
    };
}
my = new MyClass("newbie");
console.log(my.getPrivateMember());
var util = require("util");
var events = require("events");
var _ = require("underscore");

function MyStream() {
    events.EventEmitter.call(this);
    this.__MyStream = {
        _events: "",
        _maxListeners: 0
    }
}

util.inherits(MyStream, events.EventEmitter);

_.extend(MyStream.prototype, {
    write: function(data){
        this.__MyStream._events = "This will not override the super member but it's odd";
        this.emit("data", data);
    },

//    on: function(){
//        console.log("my on");
//        events.EventEmitter.prototype.on.apply(this, arguments);
//    },

    constructor: MyStream
});

var stream = new MyStream();

console.log(stream instanceof events.EventEmitter); // true
console.log(stream instanceof MyStream); // true

stream.on("data", function(data) {
    console.log('Received data: "' + data + '"');
})
stream.write("It works!"); // Received data: "It works!"
但是写这样的代码是很奇怪的,我相信很少有图书馆是这样写的。我怎么能相信使用这些LIB,就好像它们没有打破它们所拥有的LIB一样? 您可以看到node.js的核心源代码很简单,但是当您使用node.js和大量第三方库构建一个大型项目时,您是否会担心私有命名冲突

也许有人会说使用javascript的模块模式。我知道,这当然不能解决我在这里提出的问题


有没有办法解决这个问题,或者我的问题出了问题?

Javascript不是传统的面向对象语言。我知道。标题可能不准确,因此我将其更改为使用类名作为私有变量的前缀不是一个坏主意,但手动这样做是不正确的。这就是为什么您应该有一个构建系统,它通过代码转换为您实现这一点。或者您使用node.js已经支持的es6符号:致命缺陷?不,数百万JS开发人员使用原型继承,过得很好。我想你什么都不担心。也很有趣: