scope查看对象方法的问题

scope Issue seeing object methods

本文关键字:问题 方法 对象 scope      更新时间:2023-09-26

我试着搜索了很多S.O.页面,但在不使用JQUERY的情况下,没有任何内容能完全触及顶部。。。。我正在努力坚持纯JavaScript,因为在提高我目前对JQuery的了解之前,我想学习115%。

我有一个名为ScreenResizeTool的对象,如下所示。。。

function ScreenResizeTool(currImg) {
    window.addEventHandler('resize', function() {
        listen(currImg);
    }, true);
}

还有这样的方法。。。

ScreenResizeTool.prototype.listen = function(currImg) {
    //Random Code For Resizing
};

对于一个经验丰富的JavaScript用户来说,我的问题可能是显而易见的,但我很难不把它变成一个混乱、肮脏、糟糕的OOP集。我做了各种测试来向自己展示和证明addEventHandler中的this在绑定到窗口时会发生变化。这是我在测试前假设的,但我能够看到,一旦window.resize事件发生,侦听方法就消失了,而不是全局窗口变量的一部分。。。。

我还尝试在对象构造函数中添加this捕获(如this.me = this(,但它在运行后也看不到me变量。一旦窗口接管了函数,它就不再知道me变量的任何信息,也不再知道对我的类方法的任何引用。。。。

我知道我可以用不同的方式来区分这一点,但我在这里的目标是学习如何完全封装和使用尽可能多的干净的OOP结构,就像我刚从。NET世界,我的生活中需要它。

我也意识到,我可能会进行混乱的调用和/或存储此对象,或访问窗口变量中的方法,但这对我来说似乎是完全错误的。我应该能够完全封装此对象,并在该类结构中实现其事件和方法。

我也知道currImg变量也不会出现,但让我们从这里开始。我想,一旦我弄清楚了关于JavaScript范围的错误思路,我就可以解决currImg问题了。

我知道有1000个JavaScript程序员在等着问我这个简单的问题,但我必须知道。。。

有人想吗?绑定到DOM对象(如window(的函数内的

this将始终引用该对象
构造函数内部的this将始终引用prototype

正如您所提到的,规避this问题的一种常见做法是将其缓存在一个变量中,通常称为self。现在,您希望对象的变量和属性在实例化后可用,因此您需要的是return关键字,更具体地说,返回父对象本身。让我们把这些放在一起:

function ScreenResizeTool() {
  var self = this;
  // method to instantiate the code is often stored in init property
  this.init = function() {
    window.addEventListener('resize', function() {
       self.listen(); // self will refer to the prototype, not the window!
    }, true);
  };
  return this;
}
ScreenResizeTool.prototype.listen = function() { // Dummy function
  var h = window.innerHeight, w = window.innerWidth;
  console.log('Resized to ' + w + ' x ' + h + '!');
};

很简单吧?所以我们现在有了原型,但如果没有实例,原型什么都做不了。因此,我们创建了一个ScreenResizeTool的实例,并使用其init方法对其进行实例化:

var tool = new ScreenResizeTool();
tool.init();
// every time you resize the window now, a result will be logged!

您也可以简单地存储CCD_ 15&init方法作为构造函数中的私有函数,并在匿名对象中返回它们:

function ScreenResizeTool() {
  var listen = function() { ... };
  var init = function() { ... };
  // in this.init you can now simply call listen() instead of this.listen()
  return {
    listen: listen,
    init: init
  }
}

检查小提琴,并确保打开你的控制台。请注意,在这种情况下,我宁愿使用第一个函数,也不愿使用第二个函数(它的作用完全相同(,因为原型只有在您有多个实例或子类

时才有用

JavaScript中this的整个概念对初学者来说是一场噩梦,在我的代码中,我通常会尽量避免它,因为它会很快混淆并导致代码不可读(IMHO(。此外,许多刚接触JavaScript但在面向对象编程语言方面经验丰富的人试图直接进入整个thisprototype的内容,尽管他们实际上并不需要(例如,谷歌JS模式,如IIFE作为替代方案(。

所以看看你的原始代码:

function ScreenResizeTool(currImg) {
    window.addEventHandler('resize', function() {
        listen(currImg); // global function listen?
    }, true);
}
ScreenResizeTool.prototype.listen = function(currImg) {
    //Random Code For Resizing
};

首先,你可能指的是addEventListener。在它的回调中,你引用了listen,但它是一个全局变量,会将其查找为window.listen——它不会退出。所以你可以考虑这样做:

function ScreenResizeTool(currImg) {
    window.addEventHandler('resize', function() {
        this.listen(currImg); // what's this?
    }, true);
}

因为您想要使用ScreenResizeToolprototype.listen功能。但这也不起作用,因为事件侦听器的回调函数是用不同的this调用的,而不是用作为函数范围的this调用的。这就是让大多数程序员感到尴尬的地方,你必须缓存this,我看到的代码示例:

var _this = this;
var that = this;
var _self = this;

让我们只使用后者来引用事件回调中的函数:

function ScreenResizeTool(currImg) {
    var _self = this;
    window.addEventListener('resize', function() {
        _self.listen();
    }, true);
}

现在,这将实际工作并实现您想要实现的目标:调用ScreenResizeToolprototype.listen函数。有关工作示例,请参阅此JSFiddle:http://jsfiddle.net/KNw6R/(检查控制台输出(

最后,这个问题与是否使用jQuery无关。这是JS的一个普遍问题。尤其是当必须处理不同的浏览器实现时,你应该使用jQuery(或另一个这样的库(来使你自己的代码干净整洁,而不是为了找出以什么方式支持什么功能而篡改多个if语句。