JavaScript类封装GeoLocation时ShowPosition的this绑定问题
嘿,我完全懂你遇到的问题——把Geolocation代码封装到类里之后,调用this.ShowPosition()的时候this居然指向了window,这在JS里是个新手常踩的坑,尤其是涉及到类和回调函数的时候。
别担心,有好几种方法可以帮你把this正确绑定到类实例上,而且完全能保住你不想直接在ShowPosition里用getElementById的封装初衷。下面给你详细说说:
方法1:在构造函数里用bind绑定this
bind方法会创建一个新函数,强制把this绑定到你指定的对象上。你只需要在类的构造函数里把ShowPosition方法的this绑定到当前实例就行:
class GeoLocationWrapper { constructor() { // 提前获取DOM元素,保持封装性 this.locationElement = document.getElementById('your-element-id'); // 绑定ShowPosition的this到当前类实例 this.ShowPosition = this.ShowPosition.bind(this); } getLocation() { if (navigator.geolocation) { // 现在直接传ShowPosition,this已经被绑定好了 navigator.geolocation.getCurrentPosition(this.ShowPosition); } } ShowPosition(position) { console.log(this); // 现在输出的是GeoLocationWrapper实例 // 用this访问类里的属性,不用直接调用getElementById this.locationElement.textContent = `纬度: ${position.coords.latitude}, 经度: ${position.coords.longitude}`; } }
方法2:用箭头函数作为回调
箭头函数不会创建自己的this,它会继承外层作用域的this。所以你可以在调用getCurrentPosition的时候,用箭头函数包裹ShowPosition的调用:
class GeoLocationWrapper { constructor() { this.locationElement = document.getElementById('your-element-id'); } getLocation() { if (navigator.geolocation) { // 箭头函数的this就是getLocation方法里的this(也就是类实例) navigator.geolocation.getCurrentPosition((pos) => this.ShowPosition(pos)); } } ShowPosition(position) { console.log(this); // 输出类实例 this.locationElement.textContent = `纬度: ${position.coords.latitude}, 经度: ${position.coords.longitude}`; } }
方法3:用类字段的箭头函数定义ShowPosition
现在现代浏览器和转译工具(比如Babel)都支持类字段语法,你可以直接用箭头函数来定义类方法,这样方法里的this会自动绑定到类实例:
class GeoLocationWrapper { constructor() { this.locationElement = document.getElementById('your-element-id'); } getLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(this.ShowPosition); } } // 用箭头函数定义方法,this永远指向类实例 ShowPosition = (position) => { console.log(this); // 输出类实例 this.locationElement.textContent = `纬度: ${position.coords.latitude}, 经度: ${position.coords.longitude}`; } }
这三种方法都能解决你的问题,而且都能让你保持类的封装性——你可以在构造函数里提前获取DOM元素,然后通过this访问它,不用在ShowPosition里直接调用getElementById,完全符合你的初衷。
你可以根据自己的环境和偏好选一种:如果需要兼容旧浏览器,方法1最稳妥;如果想代码更简洁,方法3很合适;方法2则比较灵活,不用修改方法本身。
内容的提问来源于stack exchange,提问作者indiehjaerta
相关产品推荐
相关产品推荐

