如您所知,JavaScript在语法方面是一种非常灵活的面向对象语言,但我的问题是在JavaScript中定义函数的哪种方式很受欢迎?
只有javascript提供多种方式来帮助了解一些替代方案以便阅读其他人的代码或多种方式是基于性能原因?
1。使用功能
function Apple (type) {
this.type = type;
this.color = "red";
this.getInfo = getAppleInfo;
function getAppleInfo() {
return this.color + ' ' + this.type + ' apple';
}
}
2。使用对象文字
var apple = {
type: "macintosh",
color: "red",
getInfo: function () {
return this.color + ' ' + this.type + ' apple';
}
}
第3。单身人士使用功能
var apple = new function() {
this.type = "macintosh";
this.color = "red";
this.getInfo = function () {
return this.color + ' ' + this.type + ' apple';
};
}
答案 0 :(得分:2)
首先,我必须告诉你,我不是专家,你可能会找到更好的(完整)答案。
3种方式之间的巨大差异是原型。方法1 [Usin a function]
将允许您绑定未在其他对象之间共享的原型对象。
您可以添加Apple
对象的原型方法以及Object
对象。例如见:
//init
Object.prototype.hello = 'Hello';
Apple.prototype.world = ' World';
//Method 1
alert(apple.hello + apple.world); //Hello World
//Method 2
alert(apple.hello + apple.world); //Helloundefined
//Method 3
alert(apple.hello + apple.world); //Helloundefined
如果你想要同一个对象的多个实例,那么没有第一个方法就会有不好的时间。如您所示,如果您需要2个不同的苹果,则需要复制/粘贴和更改属性(第一种方法除外)。
//Method 1
var macintosh = new Apple('macintosh');
var otherApple = new Apple('Heisenberg')
//Method 2
var macintosh = {
type: "macintosh",
color: "red",
getInfo: function () {
return this.color + ' ' + this.type + ' apple';
}
}
var otherApple = {
type: "I'm not good with apple's name",
color: "red",
getInfo: function () {
return this.color + ' ' + this.type + ' apple';
}
}
//Method 3
var macintosh = new (function(type) {
this.type = type;
this.color = "red";
this.getInfo = function () {
return this.color + ' ' + this.type + ' apple';
};
})('macintosh');
var otherApple = new (function(type) {
this.type = type;
this.color = "red";
this.getInfo = function () {
return this.color + ' ' + this.type + ' apple';
};
})('Still not better');
在方法1和方法3中,您可以拥有局部变量。在对象外部无法访问的元素。
当你在对象中有事件处理函数时,这很有用。在这些函数中,您将丢失this
引用。幸运的是,您可以将其保存在本地变量中。以timeout
为例,不要欺骗.bind()
:
//Method 2
var apple = {
getMe : 'YES!',
setTimer : function(){
setTimeout(this.goGetHim, 500);
},
goGetHim : function(){
//alert(this.getMe); Do not work
alert(apple.getMe); //Kinda lame
}
}
// Method 1, 3
yourinitfn(){
var self = this
this.getMe : 'YES!',
this.setTimer : function(){
setTimeout(this.goGetHim, 500);
},
this.goGetHim : function(){
alert(self.getMe); //YES!
}
}
apple.self;//Undefined
我能想到的最后一件事是识别。基本上,您可以使用方法#1轻松地知道对象是苹果:
//Method 1
alert(apple instanceof Object); //True
alert(apple instanceof Apple); //True
//Method 2
alert(apple instanceof Object); //True
alert(apple instanceof Apple); //False
//Method 2
alert(apple instanceof Object); //True
alert(apple instanceof Apple); //False
如果有人能在这些问题上找到其他优势,我将不胜感激:
我从未使用过,也绝不会使用单例函数来创建对象。我已经阅读了某个地方(现在找不到引用),使用new function
这是一个不好的做法,也是一个很大的性能影响。请注意,我在这里可能错了......
答案 1 :(得分:1)
简要问题"哪种方法很受欢迎?"我必须说我已经看到了各种各样的组合在野外使用的各种不同的方法。没有标准的方法(因此有很多错误)。
有多种方法的原因是因为JS不是面向对象的语言。它是一种基于对象的脚本语言,并不是最初用于大规模应用程序和库。由于语法灵活,它允许你在5行代码中做一些看起来很壮观的事情,但是当需要大规模的健壮性和可读性时,它会变成一场噩梦。
就个人而言,我编写了一个JavaScript库,试图为JS提供一个干净自然的语法,如C ++,声明,后面的定义,以及哪些允许在JS中使用静态,私有,受保护,虚拟等成员。< / p>
OoJs can be found on GitHub。这是语法的基本示例:
;( function class_Template( namespace )
{
'use strict'; // recommended
if( namespace[ "Template" ] ) return // protect against double inclusions
namespace.Template = Template
var Static = TidBits.OoJs.setupClass( namespace, "Template", "BaseClass" )
// Static data members, private by default
//
Static.privateStaticDM = 0
Static.protectedStaticDM = 0
Static.publicStaticDM = 0
Static.Private
(
"privateStaticDM" //< can do for consistency, but private is the default
, privateStaticMethod // accesslevel for data members
)
Static.Protected
(
"protectedStaticDM"
, protectedStaticMethod
)
Static.Public
(
"publicStaticDM"
, publicStaticMethod
)
// constructor
//
function Template( parameter )
{
// Data members
//
this.privateInstanceDM = parameter
this.protectedInstanceDM = 0
this.publicInstanceDM = 0
this.Private
(
"privateInstanceDM"
, init
, this.Virtual
(
virtualPrivateInstanceMethod
)
)
this.Protected
(
"protectedInstanceDM"
, protectedInstanceMethod
)
var iFace = this.Public
(
"publicInstanceDM"
, publicInstanceMethod
)
this.init() // if you have to do something else
return iFace
}
// all your method definitions go here
//
function init(){}
function privateStaticMethod(){}
})( window )
答案 2 :(得分:0)
- 使用功能vs
- 使用对象文字
醇>
意味着您需要调用它来获取实例:
var apple = new Apple("Macintosh");
它与使用对象文字创建的对象完全相同。但是,使用构造函数可以让我们优化在多个实例之间共享一些值,主要是方法:
function getInfo() {
return this.color + ' ' + this.type + ' apple';
}
function Apple (type) {
this.type = type;
this.color = "red";
this.getInfo = getAppleInfo;
}
var apple1 = new Apple("Macintosh"),
apple2 = new Apple("Golden Delicious");
apple1.getInfo === apple2.getInfo // only one function object!
但是,通过返回对象文字,工厂函数也可以做什么。将new
与构造函数一起使用具有共享其原型对象的实例的额外优势,它们继承属性。我们可以将其简化为
function Apple (type) {
this.type = type;
this.color = "red";
}
Apple.prototype.getInfo = function getInfo() {
return this.color + ' ' + this.type + ' apple';
};
// now, having
var apple2 = new Apple("Golden Delicious");
apple2.getInfo === Apple.prototype.getInfo // still only one function object
apple2.getInfo() // and we can access it directly on instances without explicitly
// having created a property on them!
apple2 instanceof Apple // is also a feature
有关详细信息,请参阅Use of 'prototype' vs. 'this' in JavaScript?。
使用函数的单身人士
var apple = new function() {
Never ever use this。它模糊了构造函数的存在,它允许在你背后构造其他非单例实例。
答案 3 :(得分:0)
您的选项1和3基本相同。需要使用new
调用选项1才能创建实例。选项3就是立即做到这一点。但这有点奇怪,因为如果只有一个对象,你也可以只使用Option 2(object literal)。
您缺少另一个常见选项,我猜您可以调用对象工厂。在这种情况下,您基本上将Option 2包装在一个函数中,以便能够实例化该对象的多个副本。
您还缺少函数原型的任何使用,出于性能原因,这在使用方法实例化类时非常重要。例如:
var Apple = function () {
this.type = "macintosh";
this.color = "red";
};
Apple.prototype = {
getInfo: function () {
return this.color + ' ' + this.type + ' apple';
}
};
var myApple = new Apple();
在这种情况下,只存在getInfo
方法的一个副本,而在您的示例中,每次实例化苹果时都会重新创建该方法。此外,使用原型可以利用原型继承。有点令人困惑的是,有alternative ways来完成这个在较新版本的Javascript中引入的内容,但它们最终是相同的。
如果我需要一个没有任何方法的对象,或者我使用以前定义的函数作为我的方法(例如,每次实例化对象时都不创建新的函数表达式),我会使用你的选项2。否则,我会使用原型和构造函数。
我建议阅读Reg Braithwaite的JavascriptAllongé,这是free online,让我真正感受到如何充分利用Javascript功能和对象模型。