4

在开始尝试学习backbone.js 之前,我一直在尝试使用JavaScript 学习OOP。

我希望能够进行数据绑定,但我似乎无法让它工作。

我刚刚制作了一个预算网站的简单原型,您可以输入预算并输入您花费了多少,它会显示您是否已经完成。

function BudgetItem(spent, budget){

    this.setSpent = function(spent){
        this.spent = spent;
    }
    this.setBudget = function(budget){
        this.budget = budget;
    }
    this.getSpent = function(){
        return this.spent;
    }
    this.getBudget = function(){
        return this.budget;
    }

}

function BudgetType(type){
    this.getType = function(){
        return type;
    }
}

BudgetType.prototype = new BudgetItem();

$(document).ready(function(){

    var food = new BudgetType('food');

    $('.budget').html(food.getBudget());
    $('.editbudget').change(function(){
        food.setBudget($('.editbudget').data())
    });
})

到目前为止,这是我的代码。我不确定我是否做得对。我应该扩展东西吗?另外,有人可以解释如何在没有库的情况下动态绑定数据吗?

4

2 回答 2

6

首先我给你一些理论。Javascript 函数是一个动态对象,就像它一样Object,并且可以使用new关键字创建一个新实例,就像您在侦听器中所做的那样。发生这种情况时,函数本身将作为构造函数运行,而this关键字将绑定到新创建的对象。你在上面所做的实际上是在你第一次传递它们的值时动态添加新属性......这很好,但对其他读者来说不是很清楚。

现在是棘手的部分。每个函数都有一个指向“隐藏”原型对象的链接。这是由 JavaScript 运行时创建的匿名(不能通过名称访问)对象,并通过prototype属性作为对用户对象的引用传递。此 Prototype 对象还通过其constructor属性引用了该函数。要测试我自己说的话,请尝试以下操作:

BudgetItem.prototype.constructor === BudgetItem // true

综上所述,您现在可以将函数视为在幕后为您创建的(隐藏)类的构造函数,可通过函数的原型属性访问。因此,您可以将字段直接添加到 Prototype 对象中,如下所示:

function BudgetItem(spent) { 
    this.spent = spent 
}           
BudgetItem.prototype.setSpent = function(spent) { this.spent = spent };
BudgetItem.prototype.getSpent = function() { return this.spent };

另一个问题是继承和向构造函数传递参数。同样,您的版本是有效的,但您在初始化 BudgetType 时无法传递已花费和预算值。我会做的是忘记原型然后去:

function BudgetType(type, spent) {
    var instance = new BudgetItem(spent);
    instance.type = type;
    return instance;
}

这与 Scott Sauyet 上面的建议很接近,但更强大。现在您可以传递两个参数(以及更多参数)并拥有更复杂的继承树。

最后,您可以做的是通过为其他自动变量(作为参数传递或在函数内部初始化的变量)提供 getter 来创建私有(或更准确地说是伪私有)属性。这是该语言的一个特殊功能,它的工作原理如下:

function BudgetType(type, spent) {
     var instance = new BudgetItem(spent);
     instance.getType = function() {
         return type;
     }
     return instance;
}

现在您可以访问 obj.getType() 在构造函数中传递的“类型”,但不能覆盖初始值。即使您定义了 obj.type = 'New Value',getType() 也会返回传递的初始参数,因为它引用了另一个上下文,该上下文是在初始化对象时创建的,并且由于关闭而从未被释放。

希望有帮助...

于 2012-11-13T15:07:04.867 回答
1

如果您希望对象的所有实例都引用相同的成员/值,您可以使用闭包:

// create a constrctor for you object wrapped in a closure
myCon = (function() {

    // define shared members up here
    var mySharedObj = new function () {
        this.member = "a";
    }();

    // return the actual constructor   
    return function () {
        this.mySharedObj = mySharedObj;
    }
}());

// create two instances of the object
var a = new myCon();
var b = new myCon();


// Altering the shared object from one
a.mySharedObj.member = "b";

// Alters it for all
console.log(b.mySharedObj.member);





如果您想从其他对象构建对象(有点像其他语言class whatever extends baseClass),但不希望它们通过引用共享值(而不是值的克隆),您可以使用如下内容:

Object.prototype.extendsUpon = (function (_prop, _args) {
    return function (base) {
        for (var key in base) {
            if (_prop.call(base, key)) {
                this[key] = base[key];
            }
        }

        function con(child){
            this.constructor = child;
        }
        con.prototype = base.prototype;

        this.prototype = new con(this);
        this.__base__ = base.prototype;

        var args = _args.call(arguments);
        args.shift();
        base.constructor.apply(this, args);
    }
}(Object.prototype.hasOwnProperty, Array.prototype.slice));


然后在对象之上构建对象:

// Base Object Constructor
function Fruit(name) {
    this.fruitname = name;
}
Fruit.prototype.yum = function() {
    return "I had an " + this.fruitname;
}

// Object constructor that derives from the Base Object
function Favorite() {

    // Derive this object from a specified base object:
    //     @arg0  -> Object Constructor to use as base
    //     @arg1+ -> arguments passed to the BaseObject's constructor
    this.extendsUpon(Fruit, "apple");

    // From here proceed as usual

    // To access members from the base object that have been over-written,
    // use "this.__base__.MEMBER.apply(this, arguments)"
}
Favorite.prototype.yum = function() {
    return this.__base__.yum.apply(this) + " and it was my favorite";
}
var mmm = new Favorite();

// Outputs: "I had an apple and it was my favorite" 
mmm.yum();
于 2012-11-13T13:13:10.030 回答