Javascript面向对象的编程技术,这叫什么?

时间:2012-08-03 17:49:11

标签: javascript

似乎有很多技术可用于创建客户端对象。我发现真正令人困惑的是确定每种技术被称为什么。我之前使用过原型

MyObject.prototype.someMethod = function (e, a) {
      .....
};

但是我也看到了像这样的

创建的对象
MyObject.someMethod = function () {
      ....
}

第二个技术名称是什么?为什么一个人使用另一个?

4 个答案:

答案 0 :(得分:4)

第一个例子类似于定义类的方法。该类的每个实例都使用相同的代码;这种方法中的this指向调用该方法的实例。

第二种类似于在类上定义静态方法。你调用像

这样的方法

MyObject.someMethod();

在实例上调用方法没有意义。

我猜你可以调用第一个“原型方法”和第二个“构造函数/类方法”。

如果您在谈论javascript时习惯使用经典的OO术语,这在Javascript使用原型继承时有些尴尬,您可以调用第一个“实例方法”和第二个“静态方法”。

答案 1 :(得分:1)

最简单的答案是使用prototype关键字在对象上定义方法将允许该方法用于从其继承的所有对象。

JavaScript中没有类,但您可以通过使用原型对象(属性)来模拟继承。

myObject.prototype.method将为从myObject派生的所有对象添加一个“方法”(你可以在jQuery加载后对jQuery执行此操作 - $ .prototype.method [$ .fn.method]将添加一个方法所有jQuery对象,无论它们何时被创建)。

myObject.method只会向myObject添加一个“方法”,就像执行代码行时一样(静态方法)。在执行此行之前调用的任何myObject都无法访问“method”。

答案 2 :(得分:1)

Javascript使用所谓的Prototypical Inheritance来实现特征的继承。请考虑以下示例:

Superclass = function() {
   //constructor code
}

Superclass.prototype.toString=function() {
    return "Derp!";
}
Superclass.derp= function(){return 'herp!'}



var instance = new Superclass();
instance.toString();//valid
instance.derp();//fails

答案 3 :(得分:1)

这里有几件事情。 首先,在担心定义对象的方法之前,要担心对象的创建。

因此,有几种创建对象的方法。首先,您可以直接创建内联对象:

var obj = { property : "myProperty", func : function () {} };

您现在拥有一个全新的对象。 您可以在事后添加它来扩展该对象。

obj.property02 = "myOtherProperty";
obj.otherFunc = function () { return this.property02; };

但构建内联对象的缺点是 所有 属性和方法都是100%公开的。

为了解决这个问题,你可以有一个构造函数来创建和返回一个对象。

var MakeWallet = function (starting_amount, pin) {
    var balance = 0,
        wallet = {};

    wallet.add = add_balance;
    wallet.deduct = deduct_amount;
    wallet.amount = check_balance;

    return wallet;

    function check_balance (pin) { /*...*/ }
    function validate_pin (user_pin) { /*...*/ }
    function add_balance (amount, pin) { /*...*/ }
    function deduct_amount (amount, pin) { /*...*/ }

};

var myWallet = MakeWallet(1, 9274);

我的麻烦是什么? 所有数据都是防篡改的。

用户可能仍然可以重写wallet.deduct,但他们实际上不会获得该针的实际价值,或者获取钱包中的金额,或者获得我不知道的任何内部功能我希望他们拥有,包括我想授予跟踪钱包的任何内部安全号码或实体/序列号。

这就是以这种方式建设的好处。

同样,我可以在钱包中添加方法和属性,然后:

myWallet.breakItOpen = function () { return this.balance; };
myWallet.stuffIt = function () { balance = 400000000; };

但这些东西实际上都无法访问原始myWallet中的变量或函数。
只有创建时存在的功能才能访问。

在其他更传统的创建方法中,您可以使用this类似于类的构造函数。

function MakeWalletClass (starting_amount, pin) {
    var balance = 0,
        serial_and_pin = generate_serial() + "_" + pin;

    this.balance = balance;
    this.checkBalance = function () { return this.balance; };
}

var myWalletInstance = new MakeWalletClass(1, 1234);

但是有一个问题:
myWalletInstance.balance是公开的。
任何人都可以看到或改变它 不好。

我们可以通过这样做来解决这个问题:

function MakeWalletClass (starting_amount, pin) {
    var balance = 0,
        serial_and_pin = generate_serial() + "_" + pin;

    this.checkBalance = function () { return balance; };
}

var myWalletInstance = new MakeWalletClass(1, 1234);

现在,this.checkBalance正在阅读隐藏的balance变量,而不是可公开编辑的属性。

现在,MakeWalletClass.prototype

当你使用构造函数模式时(即:一个向this添加属性并返回this的函数,或者不返回任何内容 - 它在后台返回this - - 并使用new关键字调用),添加prototype属性和方法将添加可用于 EVERY 实例的属性和方法你做的对象。

因此,如果您的银行名为“The Bank of Bob”,您可以添加:

MakeWalletClass.prototype.bankName = "The Bank of Bob";

现在new MakeWalletClass();的每个实例都有一个bankName属性,每个属性都是完全相同的值,每个都将公开发布。

var yourWalletInstance = new MakeWalletClass(500, 2341);
yourWalletInstance.bankName; // "The Bank of Bob";

{<1}}属性甚至可以在 之前 将属性添加到构造函数原型中的对象上使用。

您可以采用相同的方式添加prototype方法。

prototype

糟糕!
它不起作用。

原型功能可以访问公共属性 ONLY (他们可以使用var myWalletInstance = new MakeWalletClass(1, 1234); MakeWalletClass.prototype.getBalance = function () { return balance; }; myWalletInstance.getBalance(); // undefined; 调用任何内容)。

因此,添加this.XXX属性的好处是它们可以节省大量内存。 如果你的程序需要3000个钱包,并且你在构造函数中添加了prototype,那么该函数只在内存中存在一次。

添加原型的缺点是它只能做公共事物,所以除非你想平衡或固定公共属性(提示:不要),原型对于私人工作是没用的。

因此,对于这3000个钱包,您需要3000份任何处理余额或针脚的方法。

现在你已经了解了所有这些,以及prototype function是什么......真正的区别:

prototype

MakeWalletClass.prototype.say_bankName = function () { /*...*/ };

MakeWalletClass.say_bankName = function () { /*...*/ }; 适用于实例(prototype),wallet = new MakeWalletClass的方法不适用 - 只有当你想要一个附加到{{1}的函数时它才有用}。

也许你想要一个能够返回钱包数量的函数......