我仍然试图了解这个JS继承的东西如何运作,每次我认为我拥有它......我显然不会这样做。
link:https://jsfiddle.net/jacquesvanderhoven/4qkvdn46/
var baseSettings = function ()
{
this.message = "base message";
this.getMessage = function(){
return "base message from function";
}
};
var homeSettings = function ()
{
this.name = "name";
this.getName = function()
{
return "name from function";
};
};
homeSettings.prototype = Object.create(baseSettings);
var $log = $("#log");
var base = new baseSettings();
var home = new homeSettings();
$log.html($log.html() + "<br /> baseSettings.message: '" + base.message + "'");
$log.html($log.html() + "<br /> baseSettings.getMessage(): '" + base.getMessage() + "'");
$log.html($log.html() + "<br /> homeSettings.name: '" + home.name + "'");
$log.html($log.html() + "<br /> homeSettings.getName(): '" + home.getName() + "'");
$log.html($log.html() + "<br /> homeSettings.message: '" + home.message + "'");
$log.html($log.html() + "<br /> homeSettings.getMessage(): '" + home.getMessage() + "'");
baseSettings.message:&#39;基本消息&#39;
baseSettings.getMessage():&#39;来自函数&#39;的基本消息
homeSettings.name:&#39;&#39;
homeSettings.getName():&#39;来自函数&#39;的名称
homeSettings.message:&#39; undefined&#39;
其中两个实际上抛出JS异常。
如果我添加对超级构造函数的调用,它会稍微改变一下:
链接:https://jsfiddle.net/jacquesvanderhoven/4qkvdn46/5/
var baseSettings = function ()
{
this.message = "base message";
this.getMessage = function(){
return "base message from function";
}
};
var homeSettings = function ()
{
baseSettings.call(this);
this.name = "name";
this.getName = function()
{
return "name from function";
};
};
homeSettings.prototype = Object.create(baseSettings);
var $log = $("#log");
var base = new baseSettings();
var home = new homeSettings();
$log.html($log.html() + "<br /> baseSettings.message: '" + base.message + "'");
$log.html($log.html() + "<br /> baseSettings.getMessage(): '" + base.getMessage() + "'");
$log.html($log.html() + "<br /> homeSettings.name: '" + home.name + "'");
$log.html($log.html() + "<br /> homeSettings.getName(): '" + home.getName() + "'");
$log.html($log.html() + "<br /> homeSettings.message: '" + home.message + "'");
$log.html($log.html() + "<br /> homeSettings.getMessage(): '" + home.getMessage() + "'");
baseSettings.message:&#39;基本消息&#39;
baseSettings.getMessage():&#39;来自函数&#39;的基本消息
homeSettings.name:&#39;&#39; (注意!这是空的,不应该)
homeSettings.getName():&#39;来自函数&#39;的名称
homeSettings.message:&#39;基本信息&#39;
homeSettings.getMessage():&#39;来自函数&#39;的基本消息
他们中的大多数都有效,但我无法弄清楚为什么homeSettings.name什么都不返回?
它开始向我看起来像Object.create没有做任何事情,或者更确切地说它需要调用超级构造函数来做出任何改变,但即使这样它也不完美。
删除对Object.create的调用,并将调用留给超级构造函数 链接:https://jsfiddle.net/jacquesvanderhoven/4qkvdn46/8/
var baseSettings = function ()
{
this.message = "base message";
this.getMessage = function(){
return "base message from function";
}
};
var homeSettings = function ()
{
baseSettings.call(this);
this.name = "name";
this.getName = function()
{
return "name from function";
};
};
var $log = $("#log");
var base = new baseSettings();
var home = new homeSettings();
$log.html($log.html() + "<br /> baseSettings.message: '" + base.message + "'");
$log.html($log.html() + "<br /> baseSettings.getMessage(): '" + base.getMessage() + "'");
$log.html($log.html() + "<br /> homeSettings.name: '" + home.name + "'");
$log.html($log.html() + "<br /> homeSettings.getName(): '" + home.getName() + "'");
$log.html($log.html() + "<br /> homeSettings.message: '" + home.message + "'");
$log.html($log.html() + "<br /> homeSettings.getMessage(): '" + home.getMessage() + "'");
baseSettings.message:&#39;基本消息&#39;
baseSettings.getMessage():&#39;来自函数&#39;的基本消息
homeSettings.name:&#39; name&#39;
homeSettings.getName():&#39;来自函数&#39;的名称
homeSettings.message:&#39;基本信息&#39;
homeSettings.getMessage():&#39;来自函数&#39;的基本消息
我正在研究我在SO上看到的各种例子,我不得不承认我没有达到理解为什么继承有效或无法在JS工作的地步。我遇到的另一个问题是,在各种测试中,这个&#39;这个&#39;改变,我知道发生了,但我似乎无法很好地理解为什么或什么时候,以便我确切知道发生了什么。
答案 0 :(得分:1)
JavaScript中继承的关键是原型链。每当发生属性查找时:
something.propertyName
运行时首先检查直接引用的对象。如果找不到该属性,则搜索由原型内部属性链接的对象链(通常只是一个对象)的过程。
因此,继承工作的关键是创建拥有原型链的对象。传统的方法是使用new
运算符和构造函数:
function Constructor() {}
Constructor.prototype = {
propertyName: function() { alert("hello world"); }
};
现在可以创建一个对象:
var something = new Constructor();
和引用的属性:
something.propertyName(); // "hello world"
请注意,此构造函数不会执行任何操作。 可以做某事,但它只是通过现有的原型对象来实现继承工作。
Object.create()
函数只是制作具有原型链的对象的另一种方法:
var something = Object.create({
propertyName: function() { alert("hello world"); }
});
something.propertyName(); // "hello world"
那也可以写成
var something = Object.create(Constructor.prototype);
从第一个例子中重新使用原型对象。
当然,当要用作原型的对象是在代码中创建并为此目的而保留的对象时,Object.create()
会更有意义,而不是on-on -fly对象,如上例所示。要使用您的测试代码:
var baseSettings = { // plain object, not a constructor
message: "base message",
getMessage: function() {
return "base message: " + this.message;
}
};
var homeSettings = Object.create(baseSettings, {
name: "home name",
getName: function() {
return "home name: " + this.name;
}
});
现在可以使用homeSettings
作为原型创建对象,并且他们将从该对象继承name
和getName
,message
和{{1来自getMessage
对象:
baseSettings
可以使用构造函数而不是var x = Object.create(homeSettings);
console.log(x.name); // "home name"
console.log(x.getName()); // "home name: home name"
console.log(x.message); // "base message"
console.log(x.getMessage()); // "base message: base message"
完成:
Object.create()
和function HomeBase() {};
HomeBase.prototype = homeSettings;
var x = new HomeBase();
调用的相同序列会产生相同的结果。在任何一种情况下 - 通过console.log()
或通过new
- 这些示例中Object.create()
引用的对象都没有自己的属性。
答案 1 :(得分:0)
代码中的主要问题是这一行:
homeSettings.prototype = Object.create(baseSettings);
当它只需要一个对象时,您正在将函数构造函数传递给Object.create。在这种情况下,它只会返回一个空对象。
使用Object.create进行继承非常简单。
//Base class
function Vehicle() {
this.name = "vehicle " + parseInt( Math.random()*100 );
}
Vehicle.prototype.getName = function () {
console.log( this.name );
};
//sub class
function Bike() {}
Bike.prototype = Object.create( Vehicle.prototype );
var honda = new Bike();
但是,请注意,只设置了原型引用,构造函数Vehicle永远不会执行。因此,不会复制基类中定义的公共属性。因此,Bike类将具有start方法,但没有name属性。
通过使用context作为子类调用Base类调用方法可以在一定程度上解决此问题,如下所示。
通过在子类中调用Base类调用方法,我们可以将属性从Base复制到Sub类。
但是,每个实例都会复制属性而不是原型,因此需要更多内存。
function Scooter() {
//runs on creating every new instance so the name property is copied to each instance not to prototype
Vehicle.call(this);
}
Scooter.prototype = Object.create( Vehicle.prototype );
var scooty = new Scooter();
我的github wiki page上的更多细节。