1

我的代码非常简单。对我来说,它应该工作。

var preview = WinJS.Class.define(
   function (el, options) {
       el.winControl = this;
       this.el = el;

       this.textarea = d.getElementById('preview-input');
       this.preview = d.getElementById('preview-text');
       this.form = d.getElementById('perview-form');

       this.preview.addEventListener('click', this.click, false);
       //WinJS.Utilities.query("button", this.form)
       //this.preview.addEventListener('', this.save, false);

   },

   {
       click: function (e) {
           this.form.style('display', 'block');
       }
   }
);

WinJS.Namespace.define('RegCtrl', { preview: preview });

但是当点击发生时this.form似乎是未定义的空值。为什么?我不想在类的每个方法中初始化对象。

新测试

我做了额外的测试非常小

var preview = WinJS.Class.define(
   function (el, options) {
       var test = 1;
       this.test = 1;
       this.test1();
   },

   {
       test1: function () {
           console.log(this.form, test);
       }
   }

); WinJS.Namespace.define('RegCtrl', { preview: preview });

此测试在线失败this.test1();。我现在认为这个类被称为RegCtrl.preview()而不是new RegCtrl.preview().

我如何在这个被称为new但不是简单函数的函数中隐藏?

4

3 回答 3

3

其他答案没有解释发生了什么,因此给出了不正确的建议。

JavaScript 具有一流的函数对象——您可以将它们作为值传递。这正是您设置此回调时所做的事情:

this.preview.addEventListener('click', this.click, false);

您正在获取 this.click 属性的内容,它恰好是一个函数,并将其交给 addEventListener 函数来做任何它想做的事情。

我对那里的术语非常具体-注意我专门说的是功能,而不是方法。JavaScript 并没有真正的方法构造,它只是将方法作为对象的属性。

那么“this”成员是从哪里来的呢?这是在调用者处确定的 - 您在“。”左侧使用的对象。是成为这个价值的那个。例如,

function exampleFunc() { console.log("this.myName = " + this.myName); }

var a = { myName: "Chris", doSomething: exampleFunc };
var b = { myName: "Bob", doSomething: exampleFunc };

请注意,我已将完全相同的函数分配给 doSomething 属性。会发生什么:

a.doSomething(); // Outputs "this.myName = Chris"
b.doSomething(); // Outputs "this.myName = Bob"

通过两个不同的对象调用的完全相同的函数对象具有不同的 this 指针。

exampleFunc 是一个全局函数,我们称之为:

exampleFunc() // Outputs "this.myName = undefined"

那么 undefined 是从哪里来的呢?在全局函数中,“this”设置为 window(全局范围),它没有定义 myName 属性。这也意味着您可以这样做:

myName = "Global Name"; // note, no var - we want this global
exampleFunc(); // Outputs "this.myName = Global Name"

好的,那么原始问题是怎么回事?基本上,您已将函数 this.click 传递为回调函数,但尚未传递希望调用它的“this”指针。实际上, addEventListener 没有办法传递 this 指针。结果,当调用函数时, this并不指向您的对象。我不记得它指的是什么 - 它是窗口或被点击的元素,请查看 DOM 文档以进行验证。

为了让它用正确的上下文(上下文=正确的“this”)调用正确的函数,传统的方法是使用闭包。在变量中捕获“this”,然后传入一个匿名函数,该函数使用正确的 this 指针调用您的实际回调。代码如下所示:

var preview = WinJS.Class.define(
   function (el, options) {

       // Capture your current this pointer in a global variable
       // Using "that" as the name comes from JavaScript: The Good Parts book
       var that = this;

       el.winControl = this;
       this.el = el;

       this.textarea = d.getElementById('preview-input');
       this.preview = d.getElementById('preview-text');
       this.form = d.getElementById('perview-form');

       // Note what gets passed instead of this.click:
       this.preview.addEventListener('click', 
           function (e) {
               // NOTE: Calling through "that": "this" isn't pointing to the right object anymore
               // Calling through "that" resets "this" inside the call to click
               that.click(e);
           }, false);    
   },

   {
       click: function (e) {
           this.form.style('display', 'block');
       }
   }
);

这是一种足够常见的模式,ECMAScript 5 有一个实用函数来为您构建这些包装器 - function.bind。做这个:

       this.preview.addEventListener('click', 
           this.click.bind(this),
           false);    

该构造this.click.bind(this)将构造一个新函数,在调用该函数时,会将“this”引用设置为您传递的任何内容(在本例中为“this”),然后调用您调用它的函数。

是的,“this”有很多不同的值。跟踪“this”指向的内容是掌握 JavaScript 编程的重要部分。

于 2012-11-04T18:44:35.333 回答
2

我认为您可能希望将全局 JavaScript 变量定义为:

     var myForm = document.getElementById('perview-form');

或开玩笑var myForm;在内部定义和初始化function (el, options)为:

     myForm = d.getElementById('perview-form');

现在你可以在你的函数中使用这个变量:

     myForm.style('display', 'block');

编辑:我相信您可以将此变量定义为您的第一行, WinJS.Class.define使其成为实例级变量,如下所示:

     var preview = WinJS.Class.define(
         var myForm;
         function (el, options) {
           ....
           ....
           myForm = d.getElementById('perview-form');
           ...
         },

         {
            click: function (e) {
            myForm.style('display', 'block');
         }
       });
于 2012-11-04T04:21:24.800 回答
1

如果您不知道要寻找什么,这将是一件非常难以研究的事情。我添加了一行并更改了另一行。那应该可以解决您的问题。

简而言之,this每次输入新函数时都会重置关键字,函数内部的 this 值与this外部范围的 this 不同。保留这个你想要的。的名字似乎相当普遍。clickthisthat

根据 OP 提供的链接进行编辑。
此代码未经测试。如果this现在使用不起作用,那么我会尝试this2
对不起我无法测试这个,但我在任何地方都没有框架,所以我正在做有根据的猜测。

var preview = WinJS.Class.define(

  function (el, options) {
    that = this; // No var should be needed since it is declared already
    el.winControl = this;
    this.el = el;

    this.textarea = d.getElementById('preview-input');
    this.preview = d.getElementById('preview-text');
    this.form = d.getElementById('perview-form');

    this.preview.addEventListener('click', this.click, false);
    //WinJS.Utilities.query("button", this.form)
    //this.preview.addEventListener('', this.save, false);

  },
  // This is the section for instance vars
  {
    click: function (e) {
      that.form.style('display', 'block'); // AND THIS ONE
    },
    that: null // Added instance variable
  },

  // And these are static variables
  {
    that2: null
  }
);
于 2012-11-04T04:20:37.000 回答