关于如何在JavaScript中创建类的困惑
Confusion about how to create classes in JavaScript
过去在JavaScript中创建"类"时,我是这样做的:
function Dog(name){
this.name=name;
this.sound = function(){
return "Wuf";
};
}
然而,我只是看到有人这样做:
var Dog = (function () {
function Dog(name) {
this.name = name;
}
Dog.prototype.sound = function () {
return "Wuf";
};
return Dog;
})();
你能双管齐下吗?还是我做错了?既然如此,为什么?就我们最终的结果而言,两者之间到底有什么区别?在这两种情况下,我们都可以创建一个对象,方法是:
var fido = new Dog("Fido");
fido.sound();
我希望有人能启发我。
您的方式与他们的方式有两个重要区别。
- 在自调用函数(
(function() { ... })();
)中封装 - 对方法使用
this.
上的.prototype
属性
将事物封装在一个自调用函数中,然后将结果(如return
语句中定义的)分配给一个变量,称为模块模式。这是一种常见的模式,可以确保范围得到更好的控制。
与this.sound = function()
相比,使用Dog.prototype.sound = function() {}
是优选的。不同之处在于,使用Dog
构造函数为所有对象定义一次Dog.prototype.sound
,为创建的每个Dog对象再次定义this.sound = function() {}
。
经验法则是:一个对象的个体(通常是其属性)将在this
上定义,而同一类型的所有对象共享的东西(通常是函数)将在原型上定义。
使用您的代码,您将为正在创建的每个新Dog
实例创建一个新函数sound
。Javascript的prototype
通过只创建一个所有对象实例共享的函数来避免这种情况;基本上是经典的继承。
在您展示的第二段代码中,它只是附加地封装在IIFE中,在这种情况下没有太大作用。
第一种是创建构造函数的传统方法。第二个是立即调用的函数表达式,返回构造函数。此方法允许您将变量保留在模块中,而不会泄漏到可能会出现问题的全局范围中。
就我们最终的结果而言,两者之间到底有什么区别?
正如你所看到的,它们都有相同的结果。其他人已经谈到了prototype
,所以我不在这里提及它。
第二个更可取,因为它利用了Javascript的原型继承机制。
原型
Javascript继承是造成混乱的原因,但它实际上相当简单:每个对象都有一个原型,当我们试图访问原始对象以外的属性时,我们会检查这个对象。原型本身将有一个原型;在一个简单的情况下,如Dog
,这可能是Object.prototype
。
在您的两个示例中,由于new
操作符的工作方式,我们最终将得到一个原型链,它看起来像这样:fido->Dog.prototype->Object.prototype
。因此,如果我们试图在Fido上查找name
属性,我们会在对象上找到它。另一方面,如果我们寻找hasOwnProperty
属性,我们将在Fido上找不到它,在Dog.prototype
上找不到此,然后到达Object.prototype
,在那里我们将找到它。
在sound
的情况下,您的示例在两个不同的地方定义了它:在第一种情况下,fido
和我们创建的每个其他狗都将拥有自己的函数副本。在第二种情况下,Dog.prototype
将具有该函数的单个副本,当调用该方法时,单个狗将访问该副本。这避免了在存储CCD_ 26函数的副本上浪费资源。
这也意味着我们可以扩展原型链;也许我们想要一个从Dog
继承sound
函数的Corgi
类。在第二种情况下,我们可以简单地确保Dog.prototype
在Corgi.prototype
的原型链中;在第一种情况下,我们需要创建一个真正的Dog,并将其放入原型链中。
- 如何创建独立于数组更新的组件列表
- 如何创建行为类似于本机对象的对象
- 如何创建一组从属选择列表,其中连续列表依赖于前面列表选项的选择
- 创建后如何操作谷歌地图
- 如何创建自己的JavaScript api,类似于Google Analytics
- 无法在 meanjs 中使用 highcharts-ng 创建图形.如何从 MEANJS 中的现有表创建图形
- 如何创建具有两种状态的按钮切换,其行为类似于表单输入的复选框
- 如何创建类似于Github的面包屑和移位视图效果
- 纠结于如何添加“;“全选”;功能与折扣
- Facebook”;类似于“-如何使登录选项卡重定向到另一个选项卡
- jquery创建后如何删除元素
- 困惑于如何编写OO Javascript来实现简单的类模式
- 如何创建一个RxJS缓冲区,将NodeJS中的元素分组,但不依赖于永远运行的间隔
- 如何创建独立于浏览器的 Cookie
- 如何创建一个类似于Github's文件管理器的动画
- 如何为我的web应用程序创建文档预览/视图(类似于Dropbox)
- Javascript连接一个函数,类似于如何添加文本
- 从谷歌电子表格创建表格:如何操作数据
- JSF提交按钮-表单在一秒钟内被提交X次(直到重新创建视图)-如何防止它
- PHP HttpRequest创建网页-如何处理长响应时间