Javascript 在原型继承中创建新对象时如何重写函数?
下面是JavaScript中原型继承的示例:Javascript 在原型继承中创建新对象时如何重写函数?,javascript,inheritance,javascript-objects,Javascript,Inheritance,Javascript Objects,下面是JavaScript中原型继承的示例: var human = { name: '', gender: '', planetOfBirth: 'Earth', sayGender: function () { alert(this.name + ' says my gender is ' + this.gender); }, sayPlanet: function () { alert(this.name +
var human = {
name: '',
gender: '',
planetOfBirth: 'Earth',
sayGender: function () {
alert(this.name + ' says my gender is ' + this.gender);
},
sayPlanet: function () {
alert(this.name + ' was born on ' + this.planetOfBirth);
}
};
var male = Object.create(human, {
gender: {value: 'Male'}
});
var female = Object.create(human, {
gender: {value: 'Female'}
});
var david = Object.create(male, {
name: {value: 'David'},
planetOfBirth: {value: 'Mars'}
});
var jane = Object.create(female, {
name: {value: 'Jane'}
});
david.sayGender(); // David says my gender is Male
david.sayPlanet(); // David was born on Mars
jane.sayGender(); // Jane says my gender is Female
jane.sayPlanet(); // Jane was born on Earth
现在,我想知道的是一个如何正确地“覆盖”,例如,sayPlanet
函数
我这样试过:
jane.sayPlanet = function(){
console.log("something different");
};
var jane = Object.create(female, {
name: {value: 'Jane'},
sayPlanet: function(){
console.log("something different");
}
});
var jane = Object.create(female, {
name: {
value: 'Jane',
writable: true
}
});
这是有效的
不过,我也试过这样做:
jane.sayPlanet = function(){
console.log("something different");
};
var jane = Object.create(female, {
name: {value: 'Jane'},
sayPlanet: function(){
console.log("something different");
}
});
var jane = Object.create(female, {
name: {
value: 'Jane',
writable: true
}
});
但是我得到了一个类型错误
我的问题是:
- 如何在
对象中添加
函数。创建sayPlanet
- 这到底是一种“好方法”还是有更好的(最佳实践)方法
对象中添加sayPlanet
。创建:
sayPlanet: {
value: function(){
console.log("something different");
}
}
然而,第二个问题仍然存在。此外,如果有人能更深入地解释一下,如果这是一个“好方法”这样使用它,我将不胜感激
编辑#2:正如马哈维尔在下面指出的,这是一个可怕的例子,因为事实证明,一旦jane
的名称成为对象,你就不能(如果我错了请纠正我)。创建d
编辑#3:(老兄,这会让我进入一个人们穿白大褂的特定场所)。正如@WhiteHat在下面指出的,您确实可以将name属性设置为可更新,如下所示:
jane.sayPlanet = function(){
console.log("something different");
};
var jane = Object.create(female, {
name: {value: 'Jane'},
sayPlanet: function(){
console.log("something different");
}
});
var jane = Object.create(female, {
name: {
value: 'Jane',
writable: true
}
});
然后您可以执行jane.name=“jane v2.0”代码>
老实说,这里的人们,我不知道该朝哪个方向走,似乎有这么多的选择。就在今天,我读了埃里克·埃利奥特(Eric Elliot),现在我不知道该怎么想了,因为他继续争辩说ES6的人做得不太对:哦,我想我必须再次重温克罗克福德(Crockfords)这本书,决定一个“单程”,看看我能走多远 1-它应该类似于下面的代码块:
var jane = Object.create(Female.prototype, {
name: {value: 'Jane'},
sayPlanet:{ value : function(){ alert("something different");}}
});
2-此解决方案很好,您可以从MDN中看到这一点
调用属性对象的第二个参数
的语法部分对其进行了最好的描述,请参见道具
简而言之,传递给Object.create
的第二个参数应该具有可枚举属性,每个属性都具有以下一个或多个键
可配置的
可枚举的
值
可写的
获取
设置
您应该为您分配的每个班级成员解决这些问题。
根据预期的功能
根据问题中的示例,为了在创建对象后更改值,只需添加writable:true
var human = {
name: '',
gender: '',
planetOfBirth: 'Earth',
sayGender: function () {
console.log(this.name + ' says my gender is ' + this.gender);
},
sayPlanet: function () {
console.log(this.name + ' was born on ' + this.planetOfBirth);
}
};
var male = Object.create(human, {
gender: {
value: 'Male',
writable: true
}
});
var david = Object.create(male, {
name: {
value: 'David',
writable: true
},
planetOfBirth: {
value: 'Mars',
writable: false //only born once
}
});
david.sayGender();
david.sayPlanet();
david.gender = 'Female';
david.name = 'Caitlyn';
david.planetOfBirth = 'Venus'; //(will not work, not writable)
david.sayGender();
david.sayPlanet();
我不确定javascript中是否有原型继承的最佳实践,但将原型分配给对象的经典方法是创建构造函数:
var human = {
sayPlanet:function(){
// old sayPlanet
}
}
function Person(name, sayPlanet)
{
this.name = name;
this.sayPlanet = sayPlanet;
}
Person.prototype = human;
// use your constructor function
var david = new Person('david', function(){/*new sayPlanet*/});
ES6标准中也提出了这一点,但您必须记住,它是javascript现有的基于原型的继承之上的一种语法糖,javascript中仍然没有本机类 实现继承的方法非常糟糕,我对这个例子感觉不太好
如果要更改某些值,请在创建对象后的某个时间说“planetOfBirth/gender”
- 由于对象属性默认不可枚举,因此
可配置,不可写
最佳实践始终取决于您的模型、结构和最终目标。
下面的分析是一种方法
//下面是同一个例子:让我们像理解现实生活中的问题一样来理解这一点
//创建人体对象
var人类={
名称:“”,
性别:'',
行星诞生:“地球”,
性别:功能(){
log(this.name+'表示我的性别是'+this.gender);
},
sayPlanet:函数(){
console.log(this.name+'出生于'+this.planetOfBirth');
}
};
//创建Person构造函数,稍后用于创建男性/女性对象,如David/Jane
var Person=职能(性别、姓名){
这个。性别=性别;
this.name=名称;
};
//将人指定为人构装师的原型
Person.prototype=Object.create(人);
//塞特函数可以改变一个人出生的星球
Person.prototype.setPlanetOffirt=函数(PlanetOffirt){
this.planetoforbirth=planetoforbirth;
};
//使用Person构造函数创建david对象
var david=新人(“男性”、“david”);
//将大卫的出生星球改为火星
大卫。赛特普兰托福出生(“火星”);
//使用Person构造函数创建jane对象
var jane=新人(“女性”、“jane”);
//特定于对象的函数仅可供Jane使用
jane.sayPlanet=函数(){
log(“不同的东西”);
};
david.sayGender();//大卫说我的性别是男性
david.sayPlanet();//大卫出生在火星上
jane.sayGender();//简说我的性别是女性
jane.sayPlanet();//使用Object.create
肯定是一种有效的方法,但是在我看来,这个例子本身对于Object.create的内部工作方式似乎有点误导。这篇博文在总结javascript中创建对象的不同方法方面做得非常好,但我认为Object.create
的例子并没有很好地说明它是如何工作的,这与新的/constructor
方法似乎更为相似
Object.create
允许基于原型创建对象,但不使用构造函数。这意味着所创建对象的原型链
不依赖于构造函数
,(这就是为什么它可能更容易遵循的原因,通过构造函数链接的这个原型不是很简单,也不容易遵循)。但是Object.create
仍然创建原型链
,方法与new
相同
因此,在您的示例中,当您在human
中定义name
时,例如:
var human = {
name: '',
然后当您创建jane
时:
var jane = Object.create(female, {
name: {value: 'Jane'}
你不是一个真正的艺术家