gpt4 book ai didi

javascript - 如何在javascript中做好封装

转载 作者:行者123 更新时间:2023-11-28 01:47:33 24 4
gpt4 key购买 nike

从 Java 到 AngularJS(我对所有 javascript 相关技术都是新手),我正在尝试“翻译”我的想法。我在 Jasmin 中编写了一个对象和一些测试。有些测试有效,但有一个测试一直失败,在我看来,这是一个范围问题。代码如下:

function Invoice() {

var invoicelines = new LinesHandler();

function LinesHandler() {

var lines = [];

function Line() {
var quantity = 0;
var description = '';
var rate = 0;
var total=0;

return {
getQuantity : function() {
return this.quantity;
},

setQuantity : function(quantity) {
this.quantity = quantity;
this.refreshTotal();
},

getDescription : function() {
return this.description;
},

setDescription : function(description) {
this.description = description;
},

getRate : function() {
return this.rate;
},

setRate : function(rate) {
this.rate = rate;
this.refreshTotal();
},

getTotal : function() {
return this.total;
},

refreshTotal : function() {
this.total = this.quantity * this.rate;
}
}
}

return {
getLines : function () {
return lines;
},

addLine : function(line) {
lines.push(line);
},

removeLine : function() {},

editLine : function() {},

createNewLine : function() {
return new Line();
},

getCount : function() {
return lines.length;
},

getLine : function(i) {
return lines[i];
}
}
}
return {
createNewLine : function() {return invoicelines.createNewLine();},
getLinesCount : function() {return invoicelines.getCount();},
addLine : function(line) {invoicelines.addLine(line);},
getLines : function() {return invoiceLines;},
getLinesTotal : function() {
var total = 0;
for (line in invoiceLines) {
total += line.getTotal;
};
return total;
},
getTaxesTotal: function() {}
};

}

这是失败的测试

it('Calculates invoice\'s total while adding lines', function() {
var invoice = scope.invoice;

for(var i = 1, j=10; i < 4; i++, j += 10){
var line = invoice.createNewLine();
line.setQuantity(j);
line.setRate(j);
invoice.addLine(line);
}

expect(invoice.getLinesTotal()).toBe(1400);
});

我尝试像其他函数一样直接访问invoiceLines,我尝试使用this.invoiceLines,我尝试了函数getLines(),但问题是一样的,我一直在firebug中遇到类似的问题:

ReferenceError: invoiceLines is not defined

我不太明白这个问题。为什么其他函数可以看到私有(private)成员,但 getLinesTotal 函数却看不到?还是 for 循环?

提前致谢。

PS:不要犹豫批评代码,我确信这不是用 Javascript 编写代码的最佳方式

最佳答案

关于您的标题(如何在 JavaScript 中进行良好的封装),这里有一个在构建面向对象的 JavaScript 时使用的更好的通用模式:

// Wrap a "class" module in an immediately invoked function expression.
var Parent = (function() {

// Use a function declaration to create the class's constructor function.
function Parent(param) {

// Initialize instance properties from constructor args.
this.param = param;

// Initialize any other instance properties we need.
this.initVar = "foo";
}

// Add instance methods to the class's prototype. These will not exist directly on the instance.
// Instead, JS will look at the instances's prototype to find the value.
// If you try to access a method (or property) that is not defined on this class prototype,
// JS will keep looking up the prototype chain. The order here would go:
// instance -> instance.[[prototype]] (AKA Parent.prototype) -> Object.prototype -> null
Parent.prototype.someMethod = function() {
console.log("Cheese it!");
};

// Here we just make a simple method that logs an instance property to the console.
Parent.prototype.someParentMethod = function() {
console.log(this.param);
};

// Return our now-defined class
return Parent;

// Immediately invoke the wrapping function expression, returning the Parent class.
}());

// Now lets make a class that inherits from Parent.
var Child = (function() {

// Make the child constructor
function Child() {
// If we want we can call the Parent constructor, passing our Child instance as `this`
Parent.call(this, "someParam");

// Do any other child instance initialization
}

// Set the Child prototype to a new instance of Parent. For child, the prototype chain will look like:
// instance -> instance.[[prototype]] (AKA Child.prototype) -> instance.[[prototype]].[[prototype]] (AKA Parent.prototype) -> Object.prototype -> null
Child.prototype = new Parent();

// Point the constructor property to the Child constructor (currently points to Parent)
Child.prototype.constructor = Child;

// Override a parent method
Child.prototype.someMethod = function() {
console.log("Kill all humans!");
};

// Add a method to the Child prototype
Child.prototype.someChildMethod = function() {
console.log("Here be dragons");
};

return Child;
}());

var myParent = new Parent("foobar");
var myChild = new Child();
myParent.someMethod(); // => "Cheese it!"
myChild.someMethod(); // => "Kill all humans!"
myParent.someParentMethod(); // => "foobar"
myChild.someParentMethod(); // => "someParam"
myChild.someChildMethod(); // => "Here be dragons"
myParent.someChildMethod(); // => TypeError: Object #<Parent> has no method 'someChildMethod'

我知道这可能无法直接回答您的问题。然而,它演示了如何通过继承创建封装良好的“类”。原型(prototype)系统可能需要一些时间才能理解 - 我已尽力使注释尽可能清晰。这个想法是,通过将方法附加到原型(prototype),它们只定义一次,因此占用更少的内存。如果实例本身不存在该方法,它将查找其原型(prototype)链以查看它是否在任何地方定义,直到原型(prototype)链最终到达null。另外,通过操作类原型(prototype),我们可以通过组合实现多重继承。

希望这能有所帮助。如果有任何不清楚的地方请告诉我。

关于javascript - 如何在javascript中做好封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20100936/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com