我是 JavaScript 新手(本周开始学习)。我已经完成了 CodeCademy 类(class)(实际上只是 Objects 1 && 2 部分,剩下的很无聊)。我以为我通过构造函数学习了原型(prototype)继承,但我已经开始观看 Douglas Crockford: Advanced JavaScript
就在视频的开头,他提到了两种类型的继承,我意识到,我以为我知道的一切,我都不知道。因此,我开始使用 Chrome JavaScript 控制台,并尝试使用这两种继承模型来做一些事情。
//create constructor
function MyParent(){
this.name = "joe";
this.sayHi = function(){
console.log(this.name);
}
}
//create child object and inherit from parent
var myChild1 = new MyParent();
myChild1.name
"joe"
myChild1.sayHi()
joe
//add method to MyParent, so it can be accessed from myChild1
MyParent.prototype.sayBye = function(){ console.log("bye");}
myChild1.sayBye()
bye
//create another constructor
function MyParent2(){
this.sayHi = function(){
console.log("hi");
}
}
//make it inherit from MyParent, overwriting sayHi if object is instance of MyParent2
MyParent2.prototype = new MyParent();
//overwrote sayHi
var myChild11 = new MyParent2();
myChild11.sayHi();
hi
//still same as MyParent as its not overwriten in MyParent2
myChild11.name
"joe"
比起我尝试使用 Object.create 做同样的事情:
//create an object
var myParent = {
name : "joe",
sayHi : function(){
console.log(this.name)
}
};
//it works
myParent.sayHi()
joe
//create child object
var myChild = Object.create(myParent);
myChild.sayHi()
joe
//add bye method to myChild
myChild.sayBye = function(){ console.log("bye"); }
myChild.sayBye();
bye
//add bye method to myParent - does not overwrite child's bye
myParent.sayBye = function(){ console.log("bye2"); }
//however adding sayBye2 to parent, becomes available on already created child
myParent.sayBye2 = function(){ console.log("bye2"); }
myChild.sayBye2();
bye2
//but its the parent property
myChild.hasOwnProperty("sayBye2")
false
//could make million objects inherit from each other vertically or horizontally
var myChild2 = Object.create(myChild);
myChild2.name
"joe"
到目前为止,仅凭第一印象,我确实喜欢这两个模型,也许我更喜欢后者。它似乎更具表现力和力量。
我在vs.
主题上做了一些搜索,但找不到一篇好的文章来解释每种方法的优缺点(除了后者仅受较新的浏览器支持) ,但有一个简单的解决方法)。我发现的其他帖子只是 tl: dr;有点无聊。
所以我的问题是,我应该选择哪种类型的继承。两者都有什么好处吗?两者都有什么主要缺点吗?你能把两者混在一起吗? (例如,我知道您可以将对象作为参数传递给 new Constructor()
))
谢谢
编辑: 查看在浏览器不支持的情况下创建 Object.create() 替代方法的技巧,我意识到这个 hack 是多么简单。它基本上是创建一个空的构造函数,将父对象分配为其原型(prototype)并将构建的构造函数作为新对象返回。多么巧妙的技巧!
if(typeof Object.create !== "function") { Object.create = function (o) { function F() {}; F.prototype = o; return new F(); }; }
但这意味着什么?有什么需要注意的问题吗?
最佳答案
这两种方式都同样强大。有人说,如果你不接受纯原型(prototype)方法,你就不是真正的 JavaScript 大师,但实际上一切仍然只是原型(prototype)继承,这是一个风格问题。
就我个人而言,我更喜欢使用经典方法,并结合使用 new
关键字和 constructor
函数。
为什么?
- 经典模型非常有名。
- 我不必在我的对象上实现
init
函数,只需执行constructor
已经完成的操作。您可能已经注意到,纯 原型(prototype)方法使您没有构造函数
,因此您必须实现一个初始化函数(通常称为init
)如果您需要为新创建的对象运行一些初始化逻辑。
但是,我发现纯原型(prototype)方法不太冗长,对于没有实现经典继承语言的强大背景的程序员来说可能更容易理解。
顺便说一句,对于经典模型,您应该避免的一件事是像上面那样使用new
关键字进行继承,因为您正在运行父constructor
逻辑是不必要的,它可能会产生不良的副作用。
您应该像下面这样使用 Object.create
:
function A(val) { this.val = val; }
A.prototype.alertVal = function () { alert(this.val); };
function B(val) {
A.call(this, val); //call parent constructor
}
B.prototype = Object.create(A.prototype); //inherit from A
var b = new B('test');
b.alertVal(); //test
最后,这完全取决于品味,我尊重两种方式。也许其他人会想用一些真正的优点/缺点来改进这个答案,但我找不到任何东西。
关于javascript - JavaScript 中的构造函数或对象继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15871206/