我问这个是因为我认为我找到了解决JavaScript问题的方法,而且我想知道我是否已经离开了基础。我希望在这里提出这个问题是合适的。
我相信你知道,JavaScript没有私有属性。这个问题通常使用两种模式中的一种来解决。
第一种是使用闭包在构造函数内创建特权方法,并使用this
关键字将它们绑定到对象。这是used by Douglas Crockford技术。这是一个例子:
function Person(name) {
function getName() {
return name;
}
this.who = getName;
}
这种模式的问题在于污染全局命名空间存在很大的危险:
var me = Person("Karl"); // Oops! no "new"
me.who(); // TypeError: Cannot read property 'who' of undefined
who(); // "Karl" - "who" is in global namespace!
第二种解决方案是使用module pattern。不是将特权方法绑定到this
,而是将其绑定到新对象:
function Person(name) {
function getName() {
return name;
}
return {
who: getName
}
}
var me = Person("Karl"); // No "new," but that's OK
me.who(); // "Karl"
who(); // TypeError: undefined is not a function
该模式的问题是该对象没有Person的原型链。因此,您无法正确检查其类型,也无法使用构造函数的原型扩展对象:
console.log(me instanceof Person); // "false"
Person.prototype.what = function() {
return this.constructor.name + ": " + this.who();
}
me.what(); // TypeError: undefined is not a function
我找到了解决方法。使用具有Person的原型链的临时构造函数,并返回使用临时构造函数构造的对象:
function Person(name) {
function getName() {
return name;
}
// Temporary constructor
function F() {
this.who = getName;
}
F.prototype = Person.prototype;
return new F();
}
// Can't pollute the global namespace
var me = Person("Karl");
me.who(); // "Karl"
who(); // TypeError: undefined is not a function
// Proper prototype chain: correct type checking, extensible
console.log(me instanceof Person); // "true"
Person.prototype.what = function() {
return this.constructor.name + ": " + this.who();
}
me.what(); // "Person: Karl"
我对此解决方案有几个相关的问题:
答案 0 :(得分:1)
我的问题没有答案,但建议应该以更简单的方式解决所有问题:
function Person(name) {
"use strict";
if (!this) return new Person(name);
function getName() {
return name;
}
this.who = getName;
}
Person.prototype.what = function() {
return this.constructor.name + ": " + this.who();
}
MDN documentation about function context
适用于所有浏览器的替代方案
function Person(name) {
if (!(this instanceof Person)) return new Person(name);
function getName() {
return name;
}
this.who = getName;
}
Person.prototype.what = function() {
return this.constructor.name + ": " + this.who();
}