似乎有很多技术可用于创建客户端对象。我发现真正令人困惑的是确定每种技术被称为什么。我之前使用过原型
MyObject.prototype.someMethod = function (e, a) {
.....
};
但是我也看到了像这样的
创建的对象MyObject.someMethod = function () {
....
}
第二个技术名称是什么?为什么一个人使用另一个?
答案 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}的函数时它才有用}。
也许你想要一个能够返回钱包数量的函数......