我有这段代码:
// 'Vehicle' object constructor
function Vehicle() {
this.wheels = 4;
}
// Adding 'setWheels' setter function to set 'wheels' property
Object.defineProperty(Vehicle.prototype, "setWheels", {
set: function(x) {this.wheels = x}
});
// 'Car' object constructor with 'Vehicle' as prototype
function Car() {}
Car.prototype = new Vehicle;
Car.prototype.constructor = Car;
// myCar inherits 'wheels' property and 'setWheels' method
myCar = new Car();
myCar.setWheels = 2;
我期待myCar.setWheels = 2
改变继承的属性,但是它设置myCar的本地属性,阴影继承了它。从我所看到的here设置继承属性通过setter是可能的,这意味着我做错了。但具体到底是什么?
答案 0 :(得分:2)
我希望
myCar.setWheels = 2
能够改变继承的属性,而是设置myCar
的本地属性,其中阴影继承了一个
嗯,你已经被称为" myCar
上的setter,因此您要设置其.wheels
属性。
如果要更改继承的属性,则需要在继承它的对象上更改它:
Car.prototype.setWheels = 2;
(虽然我从未见过有两个车轮的车)
请注意,通常您希望实例属性(.wheels
中设置的Vehicle
)仅在实例(如myCar
)上显示,而不是在原型上显而易见。您可以考虑changing your way of inheritance到普遍接受的那个。
您在MDN上阅读的引文:
将属性设置为对象会创建自己的属性。唯一的 获取和设置行为规则的例外是有的 带有getter或setter的继承属性。
表示当 no setter (但它是数据属性或尚未存在)时,将在赋值时生成自己的属性。如果分配给的属性定义了一个setter(自己的或继承的),那么将调用 setter函数。
的确,在您的示例中,您.setWheels
上没有创建自己的myCar
属性。
setter函数做什么它是一个完全不同的问题。它可以创建一个属性(就像你的那样,通过分配给.wheels
on the current instance, this
),或做其他事情;包括重新定义自己等疯狂的东西。
获得"预期"行为,您可以使用局部变量来存储轮数并为其使用setter / getter属性:
function Car() {}
var w = 4; // "local", could be in an IIFE
Object.defineProperty(Car.prototype, "wheels", {
set: function(x) {
w = x; // no property changes/creations involved
},
get: function() {
return w;
}
});
// yourCar inherits 'wheels'
var yourCar = new Car();
yourCar.wheels; // 4
yourCar.wheels = 2; // you've got an odd car
var myCar = new Car();
myCar.wheels; // 2 - what's wrong with my car?!
这里只有一个属性 - Car.prototype.wheels
。分配到.wheels
个实例上的Car
将调用共享 setter,后者会更新 shared 变量。请注意,这种行为通常是不受欢迎的,您不希望一个实例影响所有其他实例。
答案 1 :(得分:0)
您创建了新的Vehicle实例,因此您无法直接更改它。 当新的Vehicle返回具有属性轮的对象时,在这里您将其设置为Car.prototype意味着您正在创建一个具有新Vehicle返回的一些原型属性的函数。 所以setWheels属性也会被复制到Car.prototype。 因此,setWheels中的此运算符引用Car,当您使用setWheels设置值时,它会为car创建属性轮(覆盖使用复制/继承属性),因此它显示轮是Car的属性。尝试在setWheels设置值之前和之后控制myCar.hasOwnProperty(" wheels")。