在 JavaScript 中将类绑定到类的每个新实例

Bind class to every new instance of a class in JavaScript

提问人:Selim Choueiter 提问时间:11/6/2023 最后编辑:Selim Choueiter 更新时间:11/13/2023 访问量:158

问:

我最近被拿了一堆 JavaScript 谜语,并且真的在这个谜语上停留了大约一天半(就上下文而言,所有其他谜语最多需要 1 小时)。由于我想自己提出最终的解决方案,我将发布一段类似的代码,以便我可以抓住大致的想法并根据谜语的上下文实现它。

假设这是一段代码:

class Vehicle {
  constructor(brand, model, power) {
    this.brand = brand;
    this.model = model;
    this.power = power;
  }

  info() {
    return `This vehicle is a ${this.brand} - ${this.model}, with a power of ${this.power}`;
  }
}


//do something with my class here such that
//the next calls will return/display as follows

const v = new Vehicle('Mercedes', 'C class', 12345);
console.log(v.info()); // This vehicle is a Mercedes - C class, with a power of 12345

const {
  info
} = v;
console.log(info()); // This vehicle is a Mercedes - C class, with a power of 12345



//To keep in mind, the function should stay the same, so a call to (info === v.info) should return true;
//And only the part of the code where it says to enter the code can be changed, so the class should be untouched.

我知道这不应该是一个也许会在日常生活中使用的情况,因为它是一个谜语,只是为了挑战我们的大脑,但它挑战了我,以至于我放弃了哈哈。

我尝试循环遍历 Vehicle.prototype 的条目,并将每个作为函数且不是构造函数的条目设置为绑定到类的相同函数,或 class.prototype 或类似的东西,但它不起作用。

我该如何解决它,或者至少使它能够在每次创建该类的新实例时编辑函数调用?

编辑: 我尝试使用bind方法,甚至尝试过这样的东西

Vehicle.prototype['info'] = Vehicle.prototype['info'].bind(Vehicle.prototype);

Vehicle.prototype['info'] = Vehicle.prototype['info'].bind(Vehicle);

Vehicle.prototype['info'] = Vehicle.prototype['info'].bind(Vehicle.prototype['info']);

我尝试了许多替代方案,但它们不起作用,因为我必须将其绑定到创建的类的每个实例。因此,如果创建了一个新实例,并且在那里执行了相同的操作,则每个实例都将根据从中提取数据的实例返回数据。

JavaScript 对象

评论

0赞 Keyboard Corporation 11/6/2023
使用该方法。它创建一个新函数,该函数在调用时将其关键字设置为提供的值。bind()this
0赞 Wimanicesir 11/6/2023
如果要添加代码,请在问题中编辑!
0赞 Selim Choueiter 11/6/2023
@Wimanicesir完成了!
0赞 gog 11/6/2023
以下是似乎满足您要求的答案: jsfiddle.net/vscx5fra
0赞 gog 11/6/2023
@Bergi:下次在挥舞班锤之前,一定要费心阅读这个问题。

答:

1赞 BadPiggie 11/6/2023 #1

保持为 .您需要使用 .info === v.infotruebind()

class Vehicle {
  constructor(brand, model, power) {
    this.brand = brand;
    this.model = model;
    this.power = power;
  }

  info() {
    return `This vehicle is a ${this.brand} - ${this.model}, with a power of ${this.power}`;
  }
}

const v = new Vehicle('Mercedes', 'C class', 12345);
console.log(v.info());

const info = v.info;
console.log(info.bind(v)());

console.log(info === v.info);

更新:

gog 的另一个优雅解决方案。我在这里添加了它,因为这个问题已经结束了。

class Vehicle {
    constructor(brand, model, power) {
        this.brand = brand;
        this.model = model;
        this.power = power;
    }

    info() {
        return `This vehicle is a ${this.brand} - ${this.model}, with a power of ${this.power}`;
    }
}


let fn = Vehicle.prototype.info
Object.defineProperty(Vehicle.prototype, 'info', {
    get() {
        return this._bound ?? (this._bound = fn.bind(this))
    }
});

const v = new Vehicle('Mercedes', 'C class', 12345);
console.log(v.info());

const {
    info
} = v;

console.log(info());

console.log(info === v.info)

0赞 Keyboard Corporation 11/6/2023 #2

该方法应在类的构造函数中使用,而不是在原型上使用。bind()

如果要将方法绑定到类本身,而不是实例,可以这样做:

class Vehicle {
 static info() {
   return `This is a vehicle`;
 }
}

Vehicle.info = Vehicle.info.bind(Vehicle);

console.log(Vehicle.info()); // This is a vehicle

在这种情况下,将方法绑定到类本身。Vehicle.info = Vehicle.info.bind(Vehicle);infoVehicle

评论

0赞 Selim Choueiter 11/6/2023
但在我的情况下,它不是一个静态属性,它获得的数据是由用户传递的,而不是最初在类中传递的。info()
0赞 Elvis Adomnica 11/6/2023 #3

你面临的问题是,当你从实例中解构时,你基本上是在借用它的方法,所以不再正确绑定,你需要重新绑定它。infovthis

class Vehicle {
  constructor(brand, model, power) {
    this.brand = brand;
    this.model = model;
    this.power = power;
  }

  info() {
    return `This vehicle is a ${this.brand} - ${this.model}, with a power of ${this.power}`;
  }
}


//do something with my class here such that
//the next calls will return/display as follows

const v = new Vehicle('Mercedes', 'C class', 12345);
console.log(v.info()); // This vehicle is a Mercedes - C class, with a power of 12345

// here is where the issue starts,
// now info is no longer "connected" to v instance,
// the function is just borrowed from that object
const {
  info
} = v;
// so you need to rebind it before use
console.log(info.bind(v)()); // This vehicle is a Mercedes - C class, with a power of 12345



//To keep in mind, the function should stay the same, so a call to (info === v.info) should return true;
//And only the part of the code where it says to enter the code can be changed, so the class should be untouched.