为什么我无法通过Windows 8 JavaScript应用程序访问变量

时间:2012-11-04 04:15:58

标签: javascript windows-8 winjs

我的代码非常简单。对我来说它应该有用。

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似乎未定义为null。为什么?我不想在类的每个方法中初始化对象。

新测试

我做了一个非常小的额外测试

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但不是简单函数的函数内部进行修改?

3 个答案:

答案 0 :(得分:3)

其他答案并未解释发生了什么,因此提供的建议不正确。

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

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

您正在获取this.click属性的内容,该属性恰好是一个函数,并将其交给addEventListener函数以执行它想要的任何操作。

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

那么"这个"会员来自哪里?它是在呼叫者处确定的 - 您在'左侧使用的对象。是一个成为这个价值的人。例如,

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来自哪里呢?在全球范围内,"这个"设置为窗口(全局范围),它没有定义myName属性。这也意味着你可以这样做:

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

好的,那么原始问题又是怎么回事?基本上,你已经通过了函数this.click作为回调,但你还没有通过"这个"你希望它通过的指针。实际上,addEventListener没有办法传递this指针。因此,当调用该函数时,指向您的对象。我不记得它头顶的东西 - 无论是窗口还是被点击的元素,请查看DOM文档进行验证。

为了让它用正确的上下文调用正确的函数(context =正确的" 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"引用你传递的任何东西(在这种情况下"这个"),然后调用你调用它的函数。

是的,"这个"有很多不同的值。漂浮在周围。跟踪"这个"指向是掌握JavaScript编程的重要部分。

答案 1 :(得分:2)

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

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

或jest定义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');
         }
       });

答案 2 :(得分:1)

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

简而言之,每次输入新功能时,关键字this都会重置,this功能中的click与外部范围相同。保留您想要的thisthat的名称似乎很常见。

根据OP提供的链接进行编辑 这段代码是UNTESTED。如果使用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
  }
);