【问题标题】:JavaScript class creation with private members使用私有成员创建 JavaScript 类
【发布时间】:2012-08-31 19:54:03
【问题描述】:

我正在开发一个在 javascript 中创建类的实用程序。 它有效,问题是如何定义私有属性。

这是代码

var OO = {

    Class:function(){

        var len = arguments.length;
        var data = arguments[len-1];



        var Klass;
        if (data.constructor === Object){
            Klass = function (){};

        } else {
            Klass = data.constructor;
            delete data.constructor;                
        }



        OO.extend(Klass.prototype,data); //Classic Extend Method


        return Klass;


    },
//Simple extend method, just what I need in this case
    extend: function(target, source){
            var prop;
            for (prop in source)
                target[prop] = source [prop];

    }
}

这就是它的工作原理

// first create a class
var person = OO.Class ({
constructor: function (name, age) {
this.name = name;
this.age = age;
},

name:'',
age:'',

getName: function () {
return this.name;
},

getAge: function () {
return this.age;
}

});

这是实例

var one = new Person ('josh', 22);

还有问题:

one.age / / returns 22
one.name / / returns josh

我需要的是这些属性只能通过getName()和getAge()之类的方法访问

EDIT1:添加扩展功能

【问题讨论】:

  • 使用当前的解决方案几乎无法做到这一点。
  • 为什么有些人坚持使用经典的 JavaScript 编码?
  • 您可能对 Douglas Crockford 的 Private Members in JavaScript 文章感兴趣。
  • @RobG 是的,感谢您的链接...
  • @AlienWebguy 这个老了 :)

标签: javascript oop


【解决方案1】:

作为对象接口一部分的任何变量(即this.x 和this.y)都将是公共的。您将无法强制通过 getter 对这些变量进行外部访问。

所以,只要你有这样的代码:

getAge: function () {
    return this.age;
}

...你无法阻止:

var one = new Person ('josh', 22);
console.log(one.age);

查看 Douglas Crockford 的文章 Private Members in JavaScript。

【讨论】:

  • 基于我的代码...关于如何强制属性为私有且只能通过 getter 访问的任何想法?
  • 也许问得太多了,但你至少可以指导我,不管我必须重新定义我所做的事情
  • @Jash Gazman - 你看过我的其他答案,还是 Stylez 更简洁但类似的答案?
【解决方案2】:

更新 1:

这里是工作原型。它的工作原理除了

1.) 将构造值传递给私有成员。

 Dummy values do work however.

测试小提琴:

http://jsfiddle.net/UWRHP/11/

【讨论】:

  • 扩展实现已发布!我希望所有属性都是私有的,所以用户不能直接通过 instance.attrib 访问它,他必须定义 getter 和 setter。关于如何做到这一点的任何想法?
  • 很抱歉,从这里上网有点困难(我来自加勒比地区)。针对您的问题,我已经编辑了原始帖子,因为该实现不存在(现在)。尝试从父类扩展是一个未来的想法。
  • 就像我之前说的,从这里很难上网,所以再向我道歉,请写下你的实现,投票给你。提前致谢。
  • @Josh - 我相信这是创建隐私的方法(所有方法都不同)。 stackoverflow.com/questions/14491005/…
【解决方案3】:

如果您不想像@AlienWebguy 所建议的那样让事情变得过于复杂(并完全放弃您迄今为止所做的事情),您甚至不需要.io 成员 - 最终暴露就像就像.name 和.age 属性一样:

john.io.set('name', 'Johnny'); // still exposed!

最后,.io 对象与.name 和.age 属性一样暴露,因此这是一个复杂的解决方案,在封装和信息隐藏方面没有任何进展。 (对不起,@AlienWebguy,这就是我的感觉)

如果您尝试使用经典的继承范式并完全放弃传统的 JavaScript OOP,那么请放弃传统的函数即构造函数范式,忘记在构造函数中使用 this 引用:

// first create a constructor
var Person = function(arg0, arg1) {

    var that = {};

    // private variables

    var age = arg0;
    var name = arg1;

    // public methods

    that.getName = function() {
        return name;
    };

    that.getAge = function() {
        return age;
    };

    that.setAge = function(a) {
        age = a;
    };

    return that;

};

var john = new Person('johnathan', 33);

console.log(john.name);        // undefined
console.log(john.getName());   // 'johnathan'
console.log(john.age);        // undefined
console.log(john.getAge());   // 33
john.setAge(28);
console.log(john.getAge());   // 28
john.setName("Richard");      // Error - setName is not a function

这是 Douglas Crockford 的 Parasitic Inheritance... 的示例,但没有“继承”部分。关键是,实例变量 age 和 name 是私有的,但由于 JavaScript 的函数变量作用域,它们仍然在作用域内,因此对象的方法仍然可以操作它们。

您还会注意到name 变量没有设置器,因此这种技术合法地允许您控制对name 变量的访问 - 没有隐藏的this.name 或this.io,这将允许要操纵的变量;它完全是私人的。

【讨论】:

  • 创建本地变量 age 和 name 是多余且令人困惑的。
  • @Stylez - 冗余?什么是重复的?
  • 传递的参数已经是该范围的本地参数。您将它们重命名为 arg0 和 arg1 并无缘无故地重新分配它们。请参阅我的代码进行说明。
【解决方案4】:

闭包是由构造函数参数创建的,所以这就是你需要做的(编辑过 AlienWebguy 的代码):

var Person = function(name, age){

    this.getName = function() {
        return name;
    };

    this.getAge = function() {
        return age;
    };

};

var john = new Person('johnathan', 33);

document.writeln(john.name);        // undefined
document.writeln(john.age);         // undefined
document.writeln(john.getName());   // johnathan
document.writeln(john.getAge());    // 33

【讨论】:

  • +1 我删除了我的答案,如果 OP 不想要任何二传手,这个答案会更好。
  • 我很好奇为什么这里的几乎每个答案都有反对票!显然,人们对 JavaScript 封装的感受非常强烈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 2011-04-18
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多