为什么函数未定义,即使它使用console.dir在对象中列出?

问题描述:

我来自java的背景,而使用Extjs4.2时JavaScript很新。为什么函数未定义,即使它使用console.dir在对象中列出?

困扰我很多的是未定义函数或变量错误,如下面的示例。

说我用听众树店里听树节点事件像下面扩大:

//define a model 
    Ext.define('Person', { 
     extend: 'Ext.data.Model', 
     fields: [ 
      { name: 'id', type: 'int' }, 
      { name: 'name', type: 'string' } 
     ] 
    }); 
    //create a tree store 
    var store = Ext.create('Ext.data.TreeStore', { 
     model: 'Person', 
     root: { 
      name: 'People', 
      id : -1, 
      expanded: false 
     }, 
     proxy: { 
      type: 'ajax', 
      api: { 
       create: 'createPersons', 
       read: 'readPersons', 
       update: 'updatePersons', 
       destroy: 'destroyPersons' 
      }, 
      reader : { 
       type : "json", 
       root : "children" 
      } 
     }, 
     listeners : { 
      'beforeexpand' : function(node,eOpts){ 
       console.log("requesting child of node "+node.get("id")); 
      }, 
      'expand' : function(node, eOpts) { 
       console.dir(this); 
       //why getById undefined 
       console.info(this.getNodeById("1").get("name")); 
      } 
     } 
    }); 

我的问题是:

由于console.dir(本)印(在扩大回调函数)显示:

$className 
    "Ext.data.TreeStore" 
alias 
    ["store.tree"] 
getNodeById 
    function(a) 
    $extIsFunction 
     true 
    $isFunction 
     1 
    $name 
     "getNodeById" 
    $owner 
     A() 
    __proto__ 
     function() 
    $extIsFunction 
     true 
    $isFunction 
     1 

我们知道,这里的'this'是指Ext.data.TreeStore。我抬起头API文档,还发现了getNodeById方法,它的声明是:

getNodeById(id) : Ext.data.NodeInterface 
Returns the record node by id 
Parameters 
    id : Object 
Returns 
    Ext.data.NodeInterface 

但为什么我仍然得到错误? :

TypeError: this.getNodeById(...) is undefined 

    -->console.info(this.getNodeById("1").get("name")); 
+0

是否有可能'this'被另一个函数改变为另一个对象?而不是使用'console.dir(this)',看看'console.log(typeof this.getNodeById)'返回 – David

+1

看起来不是函数是未定义的,而是函数的结果。所以会出现错误信息,因为您尝试在未定义的结果上调用get(“name”)'。 –

+0

@ Chips_100,@David,谢谢你们俩。使用typeof得到一个返回的函数,所以getNodeById实际上是一个树存储的方法。在我错误的地方,由于json格式,服务器端没有将节点信息传递给客户端错误,所以这个。getNodeById(“1”)确实会得到未定义的节点,然后get(“name”)产生错误。看起来错误消息在它出现的地方不是很准确。 – wangdq

this可以在Javascript相当困难。与其他语言相比,函数的这个关键字在JavaScript中的行为有点不同。在大多数情况下,这个的值由函数的调用方式决定。它不能在执行过程中通过赋值来设置,并且每次调用该函数时都可能会有所不同。

'expand' : function(node, eOpts) { 
     console.dir(this); 
     //why getById undefined 
     console.info(this.getNodeById("1").get("name")); 
    } 

DOCS

果壳

expand(p, eOpts) Fires after this Panel has expanded. 

Available since: 2.3.0 

Parameters p : Ext.panel.Panel The Panel that has been expanded. 
eOpts : Object The options object passed to Ext.util.Observable.addListener. 

在您的代码是对expand事件的引用。您需要使用p或在您的案件node如上图所示,而不是

大多数Javascript你会看到类似下面的东西:

function outerFun() { 
    var self = this; 
    console.log(this) 
    function innerFun() { 
     console.log(self) 
     console.log(this) 
    } 
} 

在上面虽然变化两个功能自我没有。这是更好的练习,并使代码更易于维护人员阅读。

+0

谢谢你的回复。我找到了错误原因。当我听Tree store扩展事件时,使用this.getNodeById是可以的(尽管使用节点更好)。真正发生这种情况的是服务器端json格式错误,那么树节点还没有被初始化,所以this.getNodeById(“1”)得到了一些未定义的东西。该错误消息不太准确并且很有帮助。 – wangdq