初级JavaScript模式
Beginner JavaScript Pattern
我最近开始研究对象、闭包、作用域等等。我正试图使用这些技术实现我自己的代码,但遇到了问题。
function Person(name, age) {
this.name = name;
this.age = age;
return {
ageUp: function ageUp() {
this.age++;
},
printInfo: function printInfo() {
console.log(this.name + " is " + this.age + " years old");
},
changeName: function changeName(newName) {
this.name = newName;
}
}
}
var jeff = new Person('jeff', 28);
jeff.printInfo();
奇怪的是,这会返回undefined is undefined years old
。printInfo
属性的作用域中是否没有this.name
,因为返回的对象不记得函数?
同样奇怪的是,如果我将this.name
和this.age
的所有实例更改为常规私有变量(如var personName = name;
),那么返回的对象将以某种方式正常运行,并且我可以按预期使用ageUp
和printInfo
。
我是不是结合了两种不应该的设计模式?对此,最好的方法是什么?
问题是,当您这样做时:
return { ...
您正在创建一个新对象,该对象与new
关键字先前创建的对象(您为其指定了两个属性的对象)分离。您可能会注意到jeff instanceof Person
为false,而jeff.constructor === Object
为false。
参见此示例:
function Person(name, age) {
this.name = name;
this.age = age;
return {
theObjectThatNewCreated: this
}
}
var jeff = new Person('jeff', 28);
console.log( JSON.stringify( jeff ) );
// {"theObjectThatNewCreated":{"name":"jeff","age":28}}
console.log( jeff.constructor );
// Object
console.log( jeff.theObjectThatNewCreated.constructor );
// Person
您可以通过将名称和年龄属性分配给返回的对象而不是this
:来修复它
function Person(name, age) {
return {
name: name,
age: age,
ageUp: function ageUp() {
this.age++;
},
printInfo: function printInfo() {
console.log(this.name + " is " + this.age + " years old");
},
changeName: function changeName(newName) {
this.name = newName;
}
}
}
var jeff = new Person('jeff', 28);
jeff.printInfo();
但是Person并不是真正的构造函数,它只是一个对象工厂,用new
调用它毫无意义。它返回的对象不是Person的实例,它们是普通的旧对象。有更好的方法。
我是不是结合了两种不应该的设计模式?对此,最好的方法是什么?
我想说,您将揭示模块模式与一个普通的JavaScript构造函数相结合。
不必返回新对象,您只需始终使用this
,即可将这些函数分配为Person对象的属性,而不是新对象:
function Person(name, age) {
this.name = name;
this.age = age;
this.ageUp = function ageUp() {
this.age++;
};
this.printInfo = function printInfo() {
console.log(this.name + " is " + this.age + " years old");
};
this.changeName = function changeName(newName) {
this.name = newName;
};
}
var jeff = new Person('jeff', 28);
jeff.printInfo();
但是,由于这些函数不使用构造函数中的任何封闭变量,因此它们实际上应该添加到构造函数的原型中:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.ageUp = function ageUp() {
this.age++;
};
Person.prototype.printInfo = function printInfo() {
console.log(this.name + " is " + this.age + " years old");
};
Person.prototype.changeName = function changeName(newName) {
this.name = newName;
};
var jeff = new Person('jeff', 28);
jeff.printInfo();
您将两种模式组合在一起是正确的。首先,在正常情况下,构造函数不会返回任何内容。(有一些例外,我不会在这里深究)。
你可能想做这样的事情:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.printInfo = function() {
console.log(this.name + " is " + this.age + " years old");
};
// and so on. Now you can say
var jeff = new Person('jeff', 28);
jeff.printInfo(); // => jeff is 28 years old
我假设您希望在原型上使用这些方法,以便共享它们(但这不是强制性的)。
您正在构造函数中返回一个新对象。因此,在调用new Person(...)
时,您不会收到Person
的实例,而不会收到具有您定义的属性的转储对象。
尝试将方法对象定义为构造函数的原型:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
ageUp: function ageUp() {
this.age++;
},
printInfo: function printInfo() {
console.log(this.name + " is " + this.age + " years old");
},
changeName: function changeName(newName) {
this.name = newName;
}
}
或者,如果您想保留属性name
和age
私有,您可以在构造函数中定义方法。只需将方法分配给this.
。对于私有属性,您不必将属性本身分配给您的实例:
function Person(name, age) {
this.ageUp = function ageUp() {
age++;
};
this.printInfo = function printInfo() {
console.log(name + " is " + age + " years old");
};
this.changeName = function changeName(newName) {
name = newName;
};
}
但我更喜欢第一个例子。在第二个实例中,每个新实例都将创建新方法。在第一个示例中,所有实例都指向一个原型对象,该对象应该使用较少的内存。
在类中移除周围的return{},它应该会起作用。
- Javascript,访问一个主要对象模块模式中的每个对象
- 我是否可以检测到javascript正在被卸载(作为调试模式)
- 包含圆括号的JavaScript Regex模式
- 用于操纵DOM API的Javascript设计模式
- 用javascript创建一个看起来正常分布的模式
- 揭示模块模式(JavaScript) - 这无法访问私有方法
- 匹配每个字符,直到在行首出现模式(JavaScript)
- 用于处理成功、失败、重试的异步请求的设计模式?(JavaScript)
- 模块模式javascript不是函数
- 从自定义模块模式Javascript库调用XMLHttpRequest时不会发生任何事情
- 浏览器中的观察者模式javascript:订阅事件"添加了Dom元素“;并处理这个元素
- IE11在Iframe下的怪癖模式-javascript错误
- 返回具有链接模式javascript的项
- 命令模式 JavaScript 中的执行函数
- gsp下拉值返回NaN在IE7文档模式(javascript)
- 动态模式Javascript
- 保持服务器时间,即使在离线模式(javascript/html5)
- 我如何专业地构建我的模块模式Javascript项目
- 怪癖模式 - JavaScript 不会更新表单选择选项
- 设计模式- JavaScript.安全提取深层(可能不存在)对象属性的通用函数