如何在不更改为新对象的情况下设置对象的构造函数
How to set the constructor of an Object without changing to a new Object?
在这个相关的问题中,设置构造函数的答案是这样的:
function OldClass() {
alert("old class with incomplete constructor")
}
function ChangedClass(){
alert('new class with same prototype and more complete constructor');
}
ChangedClass.prototype = OldClass.prototype;
var theClassIWant = new ChangedClass();
这并不是真正设置构造函数,而是创建一个新对象并继承原型。如何在不更改为新对象的情况下设置对象的构造函数?有可能吗?
附言:我想要这样的东西:
//non working code
var Foo = function() {}
Foo.prototype.constructor = function(bar_val) {
this.bar = bar_val;
}
var fez = new Foo("cat")
console.log(fez.bar); // outputs: cat;
constructor
是构造函数的prototype
的属性,默认情况下指向函数本身。
修改Foo.prototype.constructor
时,此属性指向另一个函数。但是,构造函数Foo
仍然存在。因此,当您创建一个对象时,您仍然实例化构造函数Foo
,而不是Foo.prototype.constructor
指向的那个。
这就是您的代码无法工作的原因。然后让我们谈谈为什么我们需要更改构造函数以及如何更改。
在ES5及之前的版本中,我们利用原型来模拟类继承机制。看起来像这样:
// parent class
function Person(name) {
this.name = name
}
// define parent method
Person.prototype.say = function() {
console.log(this.name)
}
// child class
function Coder(name, major) {
Person.call(this, name) // inherits parent properties
this.job = 'Coding'
this.major = major
}
// inherits properties and methods from parent prototype
Coder.prototype = new Person()
// define child method
Coder.prototype.work = function() {
console.log('I write ' + this.major)
}
// instantiate a child object
var me = new Coder('Leo', 'JavaScript')
console.log(me) // {name: "Leo", job: "Coding", major: "JavaScript"}
一切看起来都很完美,但有一个问题:
console.log(me.constructor) // Person
什么?me
不是用Coder
构造的吗?为什么?
回到这个答案的第一行,再读一遍:constructor
是构造函数的prototype
的属性。
最初Coder.prototype.constructor
本身就是Coder
。但有了这条线:Coder.prototype = new Person()
,它就变了。Coder.prototype.constructor
现在等于Person.prototype.constructor
,即Person
。
有人会说,试试instanceof
。是的,有效:
me instanceof Coder // true
但它也是Person
的true
,因为Coder
是它的一个子类:
me instanceof Person // true
这没有意义,所以我们需要解决构造函数的问题。这就是为什么我们在Coder.prototype = new Person()
之后使用Coder.prototype.constructor = Coder
,以获取原始构造函数。
完整代码如下:
// parent class
function Person(name) {
this.name = name
}
Person.prototype.say = function() {
console.log(this.name)
}
// child class
function Coder(name, major) {
Person.call(this, name) // inherits parent class
this.job = 'Coding'
this.major = major
}
Coder.prototype = new Person() // inherits parent's prototype
Coder.prototype.constructor = Coder // get back constructor
Coder.prototype.work = function() {
console.log('I write ' + this.major)
}
myClass = {
constructor: function(text){
console.log(text);
}
}
let ob = Object.create(myClass);
ob.constructor("old constructor "); //Output: old constructor
myClass.constructor = function(){
console.log("new constructor ")
}
ob.constructor(); //Output: new constructor
可以对类的每个属性或函数执行此操作。
请在此处观看此视频。它完美地解释了这一点。
- 在不知道深度或父属性的情况下从对象中删除属性
- 如何在不使用 new 关键字的情况下从函数创建对象
- 如何在不知道关键字的情况下访问javascript对象值
- 在不使用循环的情况下,从一个数据库字符串值向javascript数组添加多个对象
- 如何在不删除类似侦听器的情况下从父对象中删除jQuery事件侦听器
- 是否可以在不重新渲染的情况下显示/隐藏父对象中的元素
- 在禁用ng的情况下搜索JSON对象(AngularJS)
- 如何在不安装npm的情况下一次性扩展对象
- 是否可以在不创建svg对象的情况下创建捕捉元素?[snap.svg]
- 是否可以在不序列化的情况下将对象从SilverLight传递到JavaScript
- 在知道对象值的情况下,确定数组中JS对象的索引
- 在不重构Mongo数据库的情况下,更新嵌入数组中的具有给定ID的对象
- 如何避免在这种情况下修改事件对象
- handontable:在不更改数据数组/对象的情况下隐藏某些列
- 是否可以在不加对象名称前缀的情况下调用对象的函数
- 在不使用object.Create的情况下创建具有null原型的javascript对象
- 我可以在不使用XMLHttpRequest或文档对象的情况下使用Javascript来获取网页吗
- 如何在不选择模式配置参数的情况下,使用mongoose在MongoDB模式实例化中的关联数组/对象中执行foreach
- 如何在不破坏shouldComponentUpdate的情况下传递对象/子对象作为道具
- 在不使用jQuery的情况下连接两个JSON对象