由于未定义的属性,地图失败

时间:2018-11-21 16:11:47

标签: typescript recursion mapreduce

您好,我递归地枚举了tree值,并且树中的某些nodesundefined时,我已经设置了防护措施,以确保它不会失败。即使{{1 }}-map节点出现错误:

输出错误

children

代码

Adrian has children:Marian,Dan,
Dan is leaf
Marian has children:Liviu,Farcas,
t.ngfactory.js? 
    [sm]:1 ERROR TypeError: Cannot read property 'logRecursive' of undefined
                at push../src/app/pages/tree-view/treeview.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
            at Array.map (<anonymous>)
            at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.logRecursive (tree-view.component.ts:29)
            at TreeViewComponent.push../src/app/pages/tree-view/tree-view.component.ts.TreeViewComponent.ngOnInit (tree-view.component.ts:37)
            at checkAndUpdateDirectiveInline (core.js:18537)
            at checkAndUpdateNodeInline (core.js:19801)
            at checkAndUpdateNode (core.js:19763)
            at debugCheckAndUpdateNode (core.js:20397)
            at debugCheckDirectivesFn (core.js:20357)
            at Object.eval [as updateDirectives] (TreeViewComponent_Host.ngfactory.js? [sm]:1)

模型

 public logRecursive(model:TreeModel):number{
    if(model==null || model ==undefined){
      console.log("null");
      return 0;
    }
    if(model.children ==undefined || model.children.length==0 ){
      console.log(`${model.id} is leaf`);
      return 1;
    }

    console.log(`${model.id} has children:${model.children.reduce((x,y)=>y.id+","+x,"")}`);
    var result= model.children.map(this.logRecursive).reduce((x,y)=>x+y);
    return result;
  }

PS 我已经尝试了export interface TreeModel{ id:string; children:Array<TreeModel>; } childrennull或普通undefined的所有可能的后卫组合,但仍然没有在第一级失败。在第二级失败(length==0

输入

children of 'Marian')

致电 let a:TreeModel={ id:"Adrian", children:[ {id:"Dan",children:[]}, {id:"Marian",children:[ //fails when mapping his children... {id:"Farcas",children:[]}, {id:"Liviu",children:[]} ]} ] };

1 个答案:

答案 0 :(得分:1)

问题在于调用this中的this.logRecursive是递归调用中的undefined。原因是在Javascript(以及扩展名Typescript)中,this不是由函数声明决定的,而是由调用者决定的。因此,调用者可以使用所需的任何this来调用成员函数。

当您将this.logRecursive传递给map时,map将决定用什么this来呼叫logRecursivemap不会将任何this传递给您的函数,从而导致错误。

可以通过在将函数传递给this.logRecursive.bind(this)时调用map来解决问题,以解决this是谁的问题。我不建议在Typescript中使用此功能,因为目前bind的输入类型非常弱(使用此PR,它很快会在3.2中变得更好)

另一种选择是使用箭头函数,该函数将从声明上下文中捕获this

interface TreeModel {
    id: string;
    children: Array<TreeModel>;
}
let a: TreeModel = {
    id: "Adrian",
    children: [
        { id: "Dan", children: [] },
        {
            id: "Marian", children: [  //fails when mapping his children...
                { id: "Farcas", children: [] },
                { id: "Liviu", children: [] }
            ]
        }
    ]
};

class Comp {
    logRecursive(model: TreeModel): number {
        if (model == null || model == undefined) {
            console.log("null");
            return 0;
        }
        if (model.children == undefined || model.children.length == 0) {
            console.log(`${model.id} is leaf`);
            return 1;
        }

        console.log(`${model.id} has children:${model.children.reduce((x, y) => y.id + "," + x, "")}`);
        var result = model.children.map(m => this.logRecursive(m)).reduce((x, y) => x + y);
        return result;
    }
}