如何使用原型继承覆盖 JS getter & setter 函数?
How to override the JS getter & setter function using prototypal inheritance?
需要知道如何通过使用原型继承来扩展来覆盖 getter 和 setter
下面是一个例子来理解这个问题
function A() {
this._loading = "Welcome";
}
Object.defineProperty(A.prototype, 'loading', {
get() {
return this._loading+" from A";
},
set(value) {
this._loading = value;
}
});
function B() {}
Object.defineProperty(B.prototype, 'loading', {
get() {
return this._loading+" from B";
},
set(value) {
this._loading = value;
}
});
var a=new A();
var b=new B();
b.__proto__=a; // Not sure if this is wrong. This assigns the whole prototype of A to B so that B is submerged
我的预期结果是 b.loading 应该 return 我
欢迎来自 B
取而代之的是 returning
欢迎来自 A
感谢帮助。
欢迎使用 Whosebug ;)
在 Javascript 中,您有不同的方式来处理 "inheritance"。
正如您所说,由于 proto 重新分配,您的实现无法正常工作。
1.覆盖原型
通常 it is considered bad practices 使用 __proto__
访问原型。在您的情况下,您正在重新分配 B 的整个原型,因此它只会替换所有原型。
// Here you are overriding the prototype of "b"
b.__proto__=a;
// It refers to the prototype of a, so it the equivalent of calling a.loading
b.loading
2。继承自其他原型 - ES5
function B() {
// Call the constructor of A giving the "B.this" context
A.call(this)
}
// Inherits from prototype of A
B.prototype = Object.create(A.prototype)
Object.defineProperty(B.prototype, 'loading', {
get() {
return this._loading+" from B";
}
});
// You won't need to instanciate A to inherits from it
const b = new B();
b.loading // "Welcome from B"
3。更进一步
在实际场景中,您可能希望从 A 继承一些属性,并覆盖 B 中的其他属性。因为 B 继承自 A,所以您可以从 B.prototype 和 A.prototype.[=17= 调用这两种方法]
function A() {
this._loading = "Welcome";
}
Object.defineProperty(A.prototype, "loadingA", {
get: function loading() {
return this._loading + " from A"
}
});
Object.defineProperty(A.prototype, "loading", {
get: function loading() {
return this._loading + " from A"
}
});
function B() {
A.call(this)
}
B.prototype = Object.create(A.prototype)
Object.defineProperty(B.prototype, 'loading', {
get() {
return this._loading+" from B";
}
});
var b = new B()
b.loading // Welcome from B
b.loadingA // Welcome from A
4.更进一步——ES6+
你可能想使用 ES6 class 语法糖,它不那么冗长也更容易理解 ;)
class A {
constructor() {
this._loading = "Welcome"
}
get loading() {
return this._loading + " from A"
}
}
class B extends A {
get loading() {
return this._loading + " from B"
}
}
b.loading // Welcome from B
b.loadingA // Welcome from A
需要知道如何通过使用原型继承来扩展来覆盖 getter 和 setter
下面是一个例子来理解这个问题
function A() {
this._loading = "Welcome";
}
Object.defineProperty(A.prototype, 'loading', {
get() {
return this._loading+" from A";
},
set(value) {
this._loading = value;
}
});
function B() {}
Object.defineProperty(B.prototype, 'loading', {
get() {
return this._loading+" from B";
},
set(value) {
this._loading = value;
}
});
var a=new A();
var b=new B();
b.__proto__=a; // Not sure if this is wrong. This assigns the whole prototype of A to B so that B is submerged
我的预期结果是 b.loading 应该 return 我 欢迎来自 B
取而代之的是 returning 欢迎来自 A
感谢帮助。
欢迎使用 Whosebug ;)
在 Javascript 中,您有不同的方式来处理 "inheritance"。 正如您所说,由于 proto 重新分配,您的实现无法正常工作。
1.覆盖原型
通常 it is considered bad practices 使用 __proto__
访问原型。在您的情况下,您正在重新分配 B 的整个原型,因此它只会替换所有原型。
// Here you are overriding the prototype of "b"
b.__proto__=a;
// It refers to the prototype of a, so it the equivalent of calling a.loading
b.loading
2。继承自其他原型 - ES5
function B() {
// Call the constructor of A giving the "B.this" context
A.call(this)
}
// Inherits from prototype of A
B.prototype = Object.create(A.prototype)
Object.defineProperty(B.prototype, 'loading', {
get() {
return this._loading+" from B";
}
});
// You won't need to instanciate A to inherits from it
const b = new B();
b.loading // "Welcome from B"
3。更进一步
在实际场景中,您可能希望从 A 继承一些属性,并覆盖 B 中的其他属性。因为 B 继承自 A,所以您可以从 B.prototype 和 A.prototype.[=17= 调用这两种方法]
function A() {
this._loading = "Welcome";
}
Object.defineProperty(A.prototype, "loadingA", {
get: function loading() {
return this._loading + " from A"
}
});
Object.defineProperty(A.prototype, "loading", {
get: function loading() {
return this._loading + " from A"
}
});
function B() {
A.call(this)
}
B.prototype = Object.create(A.prototype)
Object.defineProperty(B.prototype, 'loading', {
get() {
return this._loading+" from B";
}
});
var b = new B()
b.loading // Welcome from B
b.loadingA // Welcome from A
4.更进一步——ES6+
你可能想使用 ES6 class 语法糖,它不那么冗长也更容易理解 ;)
class A {
constructor() {
this._loading = "Welcome"
}
get loading() {
return this._loading + " from A"
}
}
class B extends A {
get loading() {
return this._loading + " from B"
}
}
b.loading // Welcome from B
b.loadingA // Welcome from A