Canvas动画类Animator报错:Uncaught TypeError无法读取#ctx属性
问题:requestAnimationFrame调用类私有方法时触发
Cannot read properties of undefined (reading '#ctx')错误 你创建的Animator类在调用run()后出现类型错误,核心原因是回调函数的this指向丢失:
当你将this.#update作为参数传入requestAnimationFrame时,这个方法会被作为普通函数调用,此时函数内部的this不再指向Animator实例(严格模式下会变成undefined),自然无法访问私有属性#ctx。
另外你还存在一个隐性错误:原代码直接把canvas元素传给了Animator构造函数,而不是canvas的2D上下文,这也会导致后续绘图逻辑失效。
三种可行的修复方案
方案1:在构造函数中绑定this
在类的构造函数里,将#update方法的this绑定到当前实例,确保无论怎么调用,this都指向Animator对象:
class Animator { #ctx; #requestId; constructor(ctx) { this.#ctx = ctx; this.#ctx.fillStyle = 'black'; // 绑定this到实例 this.#update = this.#update.bind(this); } #update() { this.#ctx.fillRect(10, 10, 10, 10); this.#requestId = requestAnimationFrame(this.#update); } run() { this.#requestId = requestAnimationFrame(this.#update); } pause() { if (this.#requestId) { cancelAnimationFrame(this.#requestId); } this.#requestId = null; } } // 修正上下文获取代码 const canvas = document.getElementById('c'); const ctx = canvas.getContext('2d'); const test = new Animator(ctx); test.run();
方案2:用箭头函数包裹回调
在调用requestAnimationFrame时,用箭头函数包裹#update调用,箭头函数会继承当前上下文的this:
class Animator { #ctx; #requestId; constructor(ctx) { this.#ctx = ctx; this.#ctx.fillStyle = 'black'; } #update() { this.#ctx.fillRect(10, 10, 10, 10); // 用箭头函数包裹,继承当前this this.#requestId = requestAnimationFrame(() => this.#update()); } run() { // 同样用箭头函数包裹 this.#requestId = requestAnimationFrame(() => this.#update()); } pause() { if (this.#requestId) { cancelAnimationFrame(this.#requestId); } this.#requestId = null; } } // 修正上下文获取代码 const canvas = document.getElementById('c'); const ctx = canvas.getContext('2d'); const test = new Animator(ctx); test.run();
方案3:将#update定义为箭头函数类字段
直接把私有方法定义为箭头函数,箭头函数的this会始终指向类实例:
class Animator { #ctx; #requestId; // 用箭头函数定义私有方法,绑定实例this #update = () => { this.#ctx.fillRect(10, 10, 10, 10); this.#requestId = requestAnimationFrame(this.#update); } constructor(ctx) { this.#ctx = ctx; this.#ctx.fillStyle = 'black'; } run() { this.#requestId = requestAnimationFrame(this.#update); } pause() { if (this.#requestId) { cancelAnimationFrame(this.#requestId); } this.#requestId = null; } } // 修正上下文获取代码 const canvas = document.getElementById('c'); const ctx = canvas.getContext('2d'); const test = new Animator(ctx); test.run();
内容的提问来源于stack exchange,提问作者sampathsris
相关产品推荐
相关产品推荐

