这种JavaScript编码风格有什么问题?(闭包与原型)

Gre*_*egT 7 javascript closures prototype

我们一直在争论如何最好地处理我们的JS应用程序中的对象,研究Stoyan Stefanov的书,阅读关于"新","这个","原型",闭包等的无尽的SO帖子.(事实上有这么多,他们有这么多竞争理论,表明没有完全明显的答案).

所以我们假设我们不关心私人数据.我们满足于信任用户和开发人员,不要在我们定义的方式之外混淆对象.

鉴于此,除了它似乎无视数十年的OO风格和历史之外,这种技术会出现什么问题?

// namespace to isolate all PERSON's logic
var PERSON = {};

// return an object which should only ever contain data.
// The Catch: it's 100% public

PERSON.constructor = function (name) {
     return {
         name: name
     } 
}

// methods that operate on a Person
// the thing we're operating on gets passed in

PERSON.sayHello = function (person) {
     alert (person.name); 
}

var p = PERSON.constructor ("Fred");
var q = PERSON.constructor ("Me");

// normally this coded like 'p.sayHello()'
PERSON.sayHello(p);
PERSON.sayHello(q);
Run Code Online (Sandbox Code Playgroud)

明显:

  1. 有什么可以从邪恶的方式变异"P",或者干脆人的逻辑结束了棋布阻止别人.(对于规范的"新"技术也是如此).
  2. 将'p'传递给您想要使用它的每个函数都是一件轻微的麻烦.
  3. 这是一种奇怪的方法.

但那些足够好的理由可以解雇它吗?积极的一面:

  1. 它是有效的,因为(可以说)与具有重复函数声明的闭包相对立.
  2. 看起来非常简单易懂,而不是随处可见"这个".

关键是上述隐私.我知道我会因此受到抨击,但是,寻找任何反馈.干杯.

Ply*_*ynx 9

它没有任何内在错误.但它确实放弃了使用Javascript原型系统所固有的许多优点.

  • 除了它是一个对象文字之外,你的对象对它自身一无所知.因此,instanceof无法帮助您确定其来源.你只会使用鸭子打字而陷入困境.
  • 您的方法本质上是命名空间的静态函数,您必须通过传入对象作为第一个参数来重复自己.由于具有原型的对象,你可以利用的动态调度,这样p.sayHello()可以做不同的事情PERSONANIMAL根据类型的Javascript知道.这是一种多态性.每次调用方法时,您的方法都要求您命名(并且可能会出错)类型.
  • 您实际上不需要constructor函数,因为函数已经是对象.您的PERSON变量也可以是构造函数.

你在这里做的是创建一个模块模式(如命名空间).

这是另一种模式,它保留了你拥有的东西,但提供了上述优点:

function Person(name)
{
    var p = Object.create(Person.prototype);
    p.name = name; // or other means of initialization, use of overloaded arguments, etc.
    return p;
}
Person.prototype.sayHello = function () { alert (this.name); }

var p = Person("Fred"); // you can omit "new"
var q = Person("Me");
p.sayHello();
q.sayHello();
console.log(p instanceof Person); // true
var people = ["Bob", "Will", "Mary", "Alandra"].map(Person);
        // people contains array of Person objects
Run Code Online (Sandbox Code Playgroud)