Javascript setter 结果无效
Javascript setter resulting to no effect
我正在做一个项目,而我的 setter 只是拒绝工作。我尝试了多种解决方案,例如将其设为私有(但这不起作用,因为我需要访问它),将 setters 下的值重命名为不同的值,并尝试使用或不使用括号来调用它们。
class Car {
constructor(id, image, vPosition, wins, hPosition, finishedRace) { //there is a chance I may need to remove the last 3 parms (wins,hpos and finished race)
this.id = id;
this.image = image;
this.vPosition = vPosition;
this.hPosition = hPosition;
this.finishedRace = finishedRace;
this.wins = wins;
}
get getvPosition() {
return this.vPosition;
}
/**
* @param {any} vPos
*/
set setvPosition(vPos) {
this.vPosition1 = vPos;
}
get getHPosition()
{
return this.hPosition;
}
set setHPosition(hPos)
{
this.hPosition = hPos;
}
move(Car) {
Car.setHPosition(10);
}
这是我的车 class,我正在其中创建构造函数和 getter setter。与其他方法
const cars = [
new Car("Classic", "images/car1.png", 150,0,0,0),
new Car("Bug", "images/car2.png", 350,0,0,0),
new Car("Hatchback", "images/car3.png", 550,0,0,0),
new Car("Sedan", "images/car4.png", 750,0,0,0)
];
上面的对象 Car 的数组,它就在 Car 的外面 class。
看看 Car class 中的移动方法。我稍后在代码中使用它是这样的:
cars[2].move;
let str = cars[2].getHPosition;
console.log(str);
应该在 cars[2] 上调用 setter 并将其 HPosition 设置为 10
相反,它 returns 0 就好像从未调用过 setter 一样。我知道这里一定有一些愚蠢的错误,但我很生气
我想在这种情况下,我会完全删除对 getters/setters 的依赖,而只使用您通常调用的简单 class 方法。这样 move
就可以毫无问题地调用 setHPosition
。
class Car {
constructor(id, image, vPosition, wins, hPosition, finishedRace) {
this.id = id;
this.image = image;
this.vPosition = vPosition;
this.hPosition = hPosition;
this.finishedRace = finishedRace;
this.wins = wins;
}
getvPosition() {
return this.vPosition;
}
setvPosition(vPos) {
this.vPosition1 = vPos;
}
getHPosition() {
return this.hPosition;
}
setHPosition(hPos) {
this.hPosition = hPos;
}
move(val) {
this.setHPosition(val);
}
}
const cars = [
new Car("Classic", "images/car1.png", 150, 0, 0, 0),
new Car("Bug", "images/car2.png", 350, 0, 0, 0),
new Car("Hatchback", "images/car3.png", 550, 0, 0, 0),
new Car("Sedan", "images/car4.png", 750, 0, 0, 0)
];
cars[2].move(10);
console.log(cars[2].getHPosition());
您的移动函数采用 Car 参数并移动 that 汽车而不是当前 class 实例 this
。因此,您应该更改 move 函数以获取距离值,然后调用 this.setHPosition = this.getHPosition + distance
,假设您希望将汽车从其当前位置移动一个位移,而不是移动到一个固定位置。即:
move(distance) {
this.setHPosition = this.getHPosition + distance; // or just use this.hPosition directly: this.hPosition += distance
}
请注意,getters 和 setters 是像属性一样访问的函数,因此您不使用括号,而只需将 属性 分配给 setter,或阅读 属性 以获得 getter。它是语法糖,但如果你使用它,你必须正确使用它!最好不要在 setters/getters 前面加上 'get' 和 'set' 前缀,因为这会使它们看起来像函数并且可能会造成混淆。
你的错误
您的代码可能出现意外行为的多种原因:
- 您引用,但未调用
car[2].move
。像 car[2].move()
! 这样命名
- 在
move
中,您正在尝试调用实例方法,就好像它是静态方法一样!参考 this
而不是 Car
.
- 您正在尝试调用 JS setter!不要调用它 (
setHPosition(20)
),而是给 属性 (setHPosition = val
) 赋值。
- 在
setvPosition
中,您将值分配给 属性 vPosition1
(注意 1
)。
错误可能来自对某些 JS 主题的误解。
JS 中的函数
JS是一种函数式编程语言,这意味着函数被视为so-called first-class citizens。因此,引用函数(此处:move
)但不调用它是完全有效的。
在你的例子中,你实际上想要调用函数,这是通过在函数的括号中附加一个参数列表来完成的:move()
(这里没有传递任何参数)。
测试您的函数是否已被调用的一种简单方法是在其中散布一些 console.log
s,例如Chrome 还提供了一些调试工具(我个人从未使用过)。
构造函数
构造函数在调用它们时更多是例外。您可以通过在函数名称前加上关键字 new
来调用构造函数,然后可以像调用常规函数一样调用它:new SomeConstructor(1, 2, 3)
.
(大多数命名约定都将构造函数大写。)
或者,与常规函数不同,也可以通过省略参数列表来调用构造函数:new SomeConstructor
。这等同于调用不带任何参数的构造函数:new SomeConstructor()
.
您的 move
函数未作为构造函数调用,因此它必须具有要调用的参数列表:move()
.
函数上下文
在对象上调用函数将使该对象成为函数的上下文。否则,使用周围的上下文。在顶层(全局范围),globalThis
或 null
是上下文,具体取决于您处于“草率”模式还是严格模式:
console.log("Global scope:");
(function sloppyMode() {
console.log("-sloppy: this === globalThis?", this === globalThis);
})();
(function strictMode() {
"use strict";
console.log("-strict: this === undefined?", this === undefined);
})();
console.log(""); // Ignore; for whitespace in console
const compareThis = function(compTo) { return this === compTo; };
const obj = { compareThis };
console.log("Function scope:");
console.log("-direct call: this === globalThis?", compareThis(globalThis));
console.log("-direct call: this === obj?", compareThis(obj));
console.log("-on obj: this === globalThis?", obj.compareThis(globalThis));
console.log("-on obj: this === obj?", obj.compareThis(obj));
.as-console-wrapper{top:0;max-height:unset!important}
因此,我们不需要期望将 Car
对象传递给 move
,而是可以使用 this
.
此外,参数 Car
会隐藏 class Car
,因为它在词法 scope-chain.
中较早找到
如果您希望在函数中保留两者的可访问性,一个好主意是将参数命名为(小写)car
。一般来说,最好坚持一种命名约定,以免混淆自己。
实例与静态方法
一个class在JS中同时定义了实例方法和静态方法,但是静态方法只会在上定义 class,而实例方法只会在 个实例上。
例子
考虑以下几点:
class Example {
static staticMethod() {}
instanceMethod() {}
}
staticMethod
仅在 class 对象 Example
上定义,但未在实例 new Example()
:
上定义
Example.staticMethod(); // works
new Example().staticMethod(); // fails; staticMethod is undefined on instances
对于 instanceMethod
则相反:它只在实例 new Example()
上定义,而不是在 class 对象上定义 Example
:
Example.instanceMethod(); // fails; instanceMethod is undefined on the class object
new Example().instanceMethod(); // works
Getters/setters
JS 具有 get
/set
关键字,使指定的 属性 仅在特定情况下起作用:
get
属性 类似名称的 属性 被访问(读取)时调用函数。
set
属性 类似名称的 属性 赋值时调用函数。
在这两种情况下,它们都像常规属性一样使用,而不是方法:
const object = {
_name: "my name",
get name() {
console.log("object:", "get name");
return this._name;
},
set name(v) {
console.log("object:", "set name");
this._name = v;
}
};
console.log("log:", object.name); // Uses getter
object.name = "another name"; // Uses setter
console.log("log:", object.name); // Uses getter
// Complex example:
// JS assigns right-to-left, so the expression evaluates to using the string,
// not to getting the property. Because of this, it only...
console.log("log:", object.name = "third name"); // Uses setter
// See https://262.ecma-international.org/12.0/#sec-assignment-operators-runtime-semantics-evaluation
一个对象可以有一个 getter 和 setter 用于相同的 属性(如上所示,用于 name
)。但是当定义了 getter 或 setter 时,不能在同一个对象上定义同名的数据条目(这就是为什么我改为使用 _name
)。
如您所见,这些不是 get/set 方法。 Getters/setters 通常仅在 access/assignment 期间必须执行其他功能(例如缓存、惰性初始化)或具有不可变的 属性 引用或 ...
时才使用
结论
我看不出有理由在您的 class 中使用 getters/setters。此外,none 的属性是私有的(在 classes 中可用;示例:this.#aPrivateProperty
),这就是为什么我什至不使用 get/set 方法,而是访问直接属性。
此外,我个人喜欢做的是在 class 定义中也定义属性,而不仅仅是在构造函数中。然后你的 IDE 应该自动完成属性,可能会减少像你的 vPosition1
.
这样的拼写错误
下面是我将如何编写您的代码的简化示例:
class Car {
hPosition;
vPosition;
constructor(hPos, vPos) {
this.hPosition = hPos;
this.vPosition = vPos;
}
move() { // We don't expect `Car`; we can use `this` instead!
this.hPosition = 10; // Shouldn't this be "+=" ?
}
}
const cars = [
new Car(150, 0),
new Car(350, 0),
new Car(550, 0),
new Car(750, 0)
];
cars[2].move(); // Don't forget to call!
console.log(cars[2].hPosition);
如果您仍然想使用原始代码的 getters/setters:
[=89=
class Car {
constructor(vPosition, hPosition) {
this.vPosition = vPosition;
this.hPosition = hPosition;
}
get getVPosition() { return this.vPosition; }
set setVPosition(vPos) { this.vPosition = vPos; } // Fixed typo vPosition1
get getHPosition() { return this.hPosition; }
set setHPosition(hPos) { this.hPosition = hPos; }
/* This *instance method* doesn't use *this instance* at all, so why is it not a static method?
* Also, instead of using *this instance*, it uses a passed-in instance. Why?
*/
move(car) {
car.setHPosition = 10;
}
}
const cars = [
new Car(150, 0),
new Car(350, 0),
new Car(550, 0),
new Car(750, 0)
];
cars[2].move(cars[2]); // We need to call the instance method, and then pass it the object to mutate.
let str = cars[2].getHPosition; // str now holds a number, but name suggests it holds a string.
str = String(str); // *Now* it holds a string.
console.log(str);
我正在做一个项目,而我的 setter 只是拒绝工作。我尝试了多种解决方案,例如将其设为私有(但这不起作用,因为我需要访问它),将 setters 下的值重命名为不同的值,并尝试使用或不使用括号来调用它们。
class Car {
constructor(id, image, vPosition, wins, hPosition, finishedRace) { //there is a chance I may need to remove the last 3 parms (wins,hpos and finished race)
this.id = id;
this.image = image;
this.vPosition = vPosition;
this.hPosition = hPosition;
this.finishedRace = finishedRace;
this.wins = wins;
}
get getvPosition() {
return this.vPosition;
}
/**
* @param {any} vPos
*/
set setvPosition(vPos) {
this.vPosition1 = vPos;
}
get getHPosition()
{
return this.hPosition;
}
set setHPosition(hPos)
{
this.hPosition = hPos;
}
move(Car) {
Car.setHPosition(10);
}
这是我的车 class,我正在其中创建构造函数和 getter setter。与其他方法
const cars = [
new Car("Classic", "images/car1.png", 150,0,0,0),
new Car("Bug", "images/car2.png", 350,0,0,0),
new Car("Hatchback", "images/car3.png", 550,0,0,0),
new Car("Sedan", "images/car4.png", 750,0,0,0)
];
上面的对象 Car 的数组,它就在 Car 的外面 class。
看看 Car class 中的移动方法。我稍后在代码中使用它是这样的:
cars[2].move;
let str = cars[2].getHPosition;
console.log(str);
应该在 cars[2] 上调用 setter 并将其 HPosition 设置为 10 相反,它 returns 0 就好像从未调用过 setter 一样。我知道这里一定有一些愚蠢的错误,但我很生气
我想在这种情况下,我会完全删除对 getters/setters 的依赖,而只使用您通常调用的简单 class 方法。这样 move
就可以毫无问题地调用 setHPosition
。
class Car {
constructor(id, image, vPosition, wins, hPosition, finishedRace) {
this.id = id;
this.image = image;
this.vPosition = vPosition;
this.hPosition = hPosition;
this.finishedRace = finishedRace;
this.wins = wins;
}
getvPosition() {
return this.vPosition;
}
setvPosition(vPos) {
this.vPosition1 = vPos;
}
getHPosition() {
return this.hPosition;
}
setHPosition(hPos) {
this.hPosition = hPos;
}
move(val) {
this.setHPosition(val);
}
}
const cars = [
new Car("Classic", "images/car1.png", 150, 0, 0, 0),
new Car("Bug", "images/car2.png", 350, 0, 0, 0),
new Car("Hatchback", "images/car3.png", 550, 0, 0, 0),
new Car("Sedan", "images/car4.png", 750, 0, 0, 0)
];
cars[2].move(10);
console.log(cars[2].getHPosition());
您的移动函数采用 Car 参数并移动 that 汽车而不是当前 class 实例 this
。因此,您应该更改 move 函数以获取距离值,然后调用 this.setHPosition = this.getHPosition + distance
,假设您希望将汽车从其当前位置移动一个位移,而不是移动到一个固定位置。即:
move(distance) {
this.setHPosition = this.getHPosition + distance; // or just use this.hPosition directly: this.hPosition += distance
}
请注意,getters 和 setters 是像属性一样访问的函数,因此您不使用括号,而只需将 属性 分配给 setter,或阅读 属性 以获得 getter。它是语法糖,但如果你使用它,你必须正确使用它!最好不要在 setters/getters 前面加上 'get' 和 'set' 前缀,因为这会使它们看起来像函数并且可能会造成混淆。
你的错误
您的代码可能出现意外行为的多种原因:
- 您引用,但未调用
car[2].move
。像car[2].move()
! 这样命名
- 在
move
中,您正在尝试调用实例方法,就好像它是静态方法一样!参考this
而不是Car
. - 您正在尝试调用 JS setter!不要调用它 (
setHPosition(20)
),而是给 属性 (setHPosition = val
) 赋值。 - 在
setvPosition
中,您将值分配给 属性vPosition1
(注意1
)。
错误可能来自对某些 JS 主题的误解。
JS 中的函数
JS是一种函数式编程语言,这意味着函数被视为so-called first-class citizens。因此,引用函数(此处:move
)但不调用它是完全有效的。
在你的例子中,你实际上想要调用函数,这是通过在函数的括号中附加一个参数列表来完成的:move()
(这里没有传递任何参数)。
测试您的函数是否已被调用的一种简单方法是在其中散布一些 console.log
s,例如Chrome 还提供了一些调试工具(我个人从未使用过)。
构造函数
构造函数在调用它们时更多是例外。您可以通过在函数名称前加上关键字 new
来调用构造函数,然后可以像调用常规函数一样调用它:new SomeConstructor(1, 2, 3)
.
(大多数命名约定都将构造函数大写。)
或者,与常规函数不同,也可以通过省略参数列表来调用构造函数:new SomeConstructor
。这等同于调用不带任何参数的构造函数:new SomeConstructor()
.
您的 move
函数未作为构造函数调用,因此它必须具有要调用的参数列表:move()
.
函数上下文
在对象上调用函数将使该对象成为函数的上下文。否则,使用周围的上下文。在顶层(全局范围),globalThis
或 null
是上下文,具体取决于您处于“草率”模式还是严格模式:
console.log("Global scope:");
(function sloppyMode() {
console.log("-sloppy: this === globalThis?", this === globalThis);
})();
(function strictMode() {
"use strict";
console.log("-strict: this === undefined?", this === undefined);
})();
console.log(""); // Ignore; for whitespace in console
const compareThis = function(compTo) { return this === compTo; };
const obj = { compareThis };
console.log("Function scope:");
console.log("-direct call: this === globalThis?", compareThis(globalThis));
console.log("-direct call: this === obj?", compareThis(obj));
console.log("-on obj: this === globalThis?", obj.compareThis(globalThis));
console.log("-on obj: this === obj?", obj.compareThis(obj));
.as-console-wrapper{top:0;max-height:unset!important}
因此,我们不需要期望将 Car
对象传递给 move
,而是可以使用 this
.
此外,参数 Car
会隐藏 class Car
,因为它在词法 scope-chain.
如果您希望在函数中保留两者的可访问性,一个好主意是将参数命名为(小写)car
。一般来说,最好坚持一种命名约定,以免混淆自己。
实例与静态方法
一个class在JS中同时定义了实例方法和静态方法,但是静态方法只会在上定义 class,而实例方法只会在 个实例上。
例子
考虑以下几点:
class Example {
static staticMethod() {}
instanceMethod() {}
}
staticMethod
仅在 class 对象 Example
上定义,但未在实例 new Example()
:
Example.staticMethod(); // works
new Example().staticMethod(); // fails; staticMethod is undefined on instances
对于 instanceMethod
则相反:它只在实例 new Example()
上定义,而不是在 class 对象上定义 Example
:
Example.instanceMethod(); // fails; instanceMethod is undefined on the class object
new Example().instanceMethod(); // works
Getters/setters
JS 具有 get
/set
关键字,使指定的 属性 仅在特定情况下起作用:
get
属性 类似名称的 属性 被访问(读取)时调用函数。set
属性 类似名称的 属性 赋值时调用函数。
在这两种情况下,它们都像常规属性一样使用,而不是方法:
const object = {
_name: "my name",
get name() {
console.log("object:", "get name");
return this._name;
},
set name(v) {
console.log("object:", "set name");
this._name = v;
}
};
console.log("log:", object.name); // Uses getter
object.name = "another name"; // Uses setter
console.log("log:", object.name); // Uses getter
// Complex example:
// JS assigns right-to-left, so the expression evaluates to using the string,
// not to getting the property. Because of this, it only...
console.log("log:", object.name = "third name"); // Uses setter
// See https://262.ecma-international.org/12.0/#sec-assignment-operators-runtime-semantics-evaluation
一个对象可以有一个 getter 和 setter 用于相同的 属性(如上所示,用于 name
)。但是当定义了 getter 或 setter 时,不能在同一个对象上定义同名的数据条目(这就是为什么我改为使用 _name
)。
如您所见,这些不是 get/set 方法。 Getters/setters 通常仅在 access/assignment 期间必须执行其他功能(例如缓存、惰性初始化)或具有不可变的 属性 引用或 ...
时才使用结论
我看不出有理由在您的 class 中使用 getters/setters。此外,none 的属性是私有的(在 classes 中可用;示例:this.#aPrivateProperty
),这就是为什么我什至不使用 get/set 方法,而是访问直接属性。
此外,我个人喜欢做的是在 class 定义中也定义属性,而不仅仅是在构造函数中。然后你的 IDE 应该自动完成属性,可能会减少像你的 vPosition1
.
下面是我将如何编写您的代码的简化示例:
class Car {
hPosition;
vPosition;
constructor(hPos, vPos) {
this.hPosition = hPos;
this.vPosition = vPos;
}
move() { // We don't expect `Car`; we can use `this` instead!
this.hPosition = 10; // Shouldn't this be "+=" ?
}
}
const cars = [
new Car(150, 0),
new Car(350, 0),
new Car(550, 0),
new Car(750, 0)
];
cars[2].move(); // Don't forget to call!
console.log(cars[2].hPosition);
如果您仍然想使用原始代码的 getters/setters:
[=89=class Car {
constructor(vPosition, hPosition) {
this.vPosition = vPosition;
this.hPosition = hPosition;
}
get getVPosition() { return this.vPosition; }
set setVPosition(vPos) { this.vPosition = vPos; } // Fixed typo vPosition1
get getHPosition() { return this.hPosition; }
set setHPosition(hPos) { this.hPosition = hPos; }
/* This *instance method* doesn't use *this instance* at all, so why is it not a static method?
* Also, instead of using *this instance*, it uses a passed-in instance. Why?
*/
move(car) {
car.setHPosition = 10;
}
}
const cars = [
new Car(150, 0),
new Car(350, 0),
new Car(550, 0),
new Car(750, 0)
];
cars[2].move(cars[2]); // We need to call the instance method, and then pass it the object to mutate.
let str = cars[2].getHPosition; // str now holds a number, but name suggests it holds a string.
str = String(str); // *Now* it holds a string.
console.log(str);