Node.js 类的创建
返回对象的函数是创建类似对象的好方法。
例1
以下代码显示了如何使用此模式创建对象。
function Message() {
var message = "hello";
function setMessage(newMessage) {
if (!newMessage)
throw new Error("cannot set empty message");
message = newMessage;
}
function getMessage() {
return message;
}
function printMessage() {
console.log(message);
}
return {
setMessage: setMessage,
getMessage: getMessage,
printMessage: printMessage
};
}
// Pattern in use
var hi1 = Message();
hi1.printMessage(); // hello
var hi2 = Message();
hi2.setMessage("hi");
hi2.printMessage(); // hi
hi1.printMessage(); // hello
了解这一点
Javascript的 this
对象的行为不同取决于我们如何称呼它。this
对象指的是调用上下文。调用上下文是用于调用函数的前缀。
var myData = {
myValue: 123,
myFunction: function () {
console.log("inside this.myValue is:", this.myValue);
}
}
console.log("myData.myValue is: ", myData.myValue); // myData.myValue is: 123
myData.myFunction(); // inside this.myValue is: 123
默认调用上下文是Node.js全局变量。
function myData() {
console.log("is this called from globals? : ", this === global); // true
}
myData();
我们可以附加一个函数到任何对象并改变调用上下文。
var myData = {
myValue: 123
};
function myFunction() {
if (this === global)
console.log("called from global");
if (this === myData)
console.log("called from myData");
}
// global context
myFunction(); // called from global
// from myData
myData.myFunction = myFunction;
myData.myFunction(); // called from myData
如果你使用JavaScript运算符new
调用函数,它创建一个新的JavaScript对象,并且这个在函数内引用这个新创建的对象。
function myData() {
this.myData = 123;
console.log("Is this global?: ", this == global);
}
// without the new operator
myData(); // Is this global?: true
console.log(global.myData); // 123
// with the new operator
var newFoo = new myData(); // Is this global?: false
console.log(newFoo.myData); // 123
在上面的代码中,我们在函数中修改了this.myData,并将newFoo.myData设置为该值。
理解原型
JavaScript中的每个对象都有一个指向另一个对象的内部链接,称为原型。当读取对象上的属性时,myData.myValue从myData读取属性myValue,JavaScript检查myData上是否存在此属性。如果没有,JavaScript检查属性是否存在于myData. proto以及proto本身。如果在任何级别找到一个值,则返回它。否则,JavaScript返回undefined。
var shape = {};
shape.__proto__.myValue= 123;
console.log(shape.myValue); // 123
JavaScript中的“”前缀不应该由用户代码使用。在函数上使用new运算符创建对象时,proto__设置为函数的“.prototype”成员。
function shape() { };
shape.prototype.myValue = 123;
var bas = new shape();
console.log(bas.__proto__ === shape.prototype); // true
console.log(bas.myValue); // 123
注意1
从相同的函数创建的原型在所有对象之间共享。
function shape() { };
shape.prototype.myValue = 123;
var bas = new shape();
var myItem = new shape();
console.log(bas.myValue); // 123
console.log(myItem.myValue); // 123
shape.prototype.myValue = 456;
console.log(bas.myValue); // 456
console.log(myItem.myValue); // 456
上面的代码生成以下结果。
假设我们有1000个实例创建了某个对象,而原型的所有属性和函数都是共享的。因此原型节省了内存。
注意2
原型属性由对象上的属性隐藏。
function shape() { };
shape.prototype.myValue = 123;
var bas = new shape();
var myItem = new shape();
bas.myValue = 456;
console.log(bas.myValue);
console.log(myItem.myValue); // 123
this
对象是一个完美的读取/写入属性(数据)的候选,你应该将其用于所有属性(数据)。但函数一般不会在创建后改变。所以函数是放在 .prototype
上的很好的选择。函数性(函数/方法)在所有实例之间共享,而属性属于单个对象。
例2
以下代码显示了在JavaScript中编写类的模式。
function someClass() {
// Properties go here
this.someProperty = "some initial value";
}
// Member functions go here:
someClass.prototype.someMemberFunction = function () {
this.someProperty = "modified value";
console.log("called from prototype");
}
// Creation
var instance = new someClass();
// Usage
console.log(instance.someProperty); // some initial value
instance.someMemberFunction();
console.log(instance.someProperty); // modified value
上面的代码生成以下结果。
在成员函数中,我们可以使用this访问当前实例,即使在所有实例之间共享相同的函数体。核心Node.js中的大多数类都是使用此模式编写的。