0

I have tried searching through a lot of S.O. pages but nothing has touched EXACTLY on this top while also NOT USING JQUERY.... I am trying to stick to pure JavaScript as I want to learn it 115% before advancing my current knowledge of JQuery.

I have an object called ScreenResizeTool like this...

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

and a method like this...

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

My trouble is probably obvious to an experienced JavaScript user but I am having trouble not making this into a messy dirty awful OOP set. I have done various tests to show and prove to myself that the this inside the addEventHandler changes when it becomes bound to the window. This much I assumed before testing but I was able to see that once window.resize event happens the listen method is gone and not a part of the global window variable....

I have also tried adding a this capture such as this.me = this inside the object constructor however it also couldn't see the me variable once it ran. Once the window took the function over it no longer knew anything about the me variable or any reference to my class methods....

I am aware that I could separate this differently but my goal here is to learn how to fully encapsulate and use as many clean OOP structures as possible as I just came from the .NET world and I need it in my life.

I am also aware that I could make messy calls and or store this object or access to the methods inside the window variable but that seems outright wrong to me. I should be able to fully encapsulate this object and have its events and methods all implemented in this class structure.

I also know that the currImg variable is not going to be seen either but lets start small here. I assume once I figure out my incorrect train of thought on scope for JavaScript I should be fine to figure out the currImg problem.

I know there's 1000 JavaScript programmers out there waiting to rip me a new one over asking this simple question but I gotta know...

Thoughts anyone?

4

2 回答 2

1

this在绑定到 DOM 对象(如window)的函数内部将始终引用该对象。
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!

您还可以简单地将listen&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
  }
}

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

于 2014-07-13T17:50:51.603 回答
1

JavaScript 中的整个概念this对于初学者来说是一场噩梦,在我的代码中,我通常会尽量避免它,因为它会很快变得混乱并使代码不可读(恕我直言)。此外,许多对 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);
}

因为你想使用的prototype.listen功能ScreenResizeTool。但这也不起作用,因为事件侦听器的回调函数是用不同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);
}

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

最后一句话,这个问题与是否使用 jQuery 没有任何关系。这是JS的普遍问题。尤其是当必须处理不同的浏览器实现时,您应该使用 jQuery(或其他此类库)来使您自己的代码干净整洁,而不是摆弄多个 if 语句来找出以何种方式支持的功能。

于 2014-07-10T13:49:09.397 回答