最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

angular - Is there a JavaScript undefined property handling like in Angular2 templates - Stack Overflow

programmeradmin1浏览0评论

I was wondering if there is a neat way of doing this:

if (app && app.object && app.object.foo) {
  alert(app.object.foo.bar);
}

This is really long and "ugly".

I found out that Angular2 has something really great for cases like this. But I think it's only for templates:

<div>{{this?.object?.foo?.bar}}</div>

This got me really exited because I have a lot of code that looks just like the first example. It get's the job done but I'm really hopping there is something more sophisticated.

I was wondering if there is a neat way of doing this:

if (app && app.object && app.object.foo) {
  alert(app.object.foo.bar);
}

This is really long and "ugly".

I found out that Angular2 has something really great for cases like this. But I think it's only for templates:

<div>{{this?.object?.foo?.bar}}</div>

This got me really exited because I have a lot of code that looks just like the first example. It get's the job done but I'm really hopping there is something more sophisticated.

Share Improve this question asked Jun 29, 2016 at 11:19 drinovcdrinovc 5515 silver badges16 bronze badges 2
  • 1 I would like to note that if any of app or app.object or app.object.foo is not truthy like number 0 this will return false. – eko Commented Jun 29, 2016 at 11:34
  • 1 Just FYI, what you are describing is a feature of TypeScript, not of Angular2. Angular2 (optionally) makes use of TypeScript, which is why you see the feature in the Angular2 documentation. – jamesblacklock Commented Jun 29, 2016 at 15:50
Add a comment  | 

4 Answers 4

Reset to default 10

Many languages have this functionality, some call it safe navigation operator or even Elvis operator (yes haha).

JavaScript does not have this functionality. If you are open to use CoffeeScript, you might take a look at the existential operator.

But, if you want to keep with JS, you should take a look at lodash.get(), which lets you do something like this:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// → 3

_.get(object, 'a.b.d.c', 'default');
// → 'default'

I found this solution sometime back on net :

function checkNested(obj /*, level1, level2, ... levelN*/) {
  var args = Array.prototype.slice.call(arguments, 1);

  for (var i = 0; i < args.length; i++) {
    if (!obj || !obj.hasOwnProperty(args[i])) {
      return false;
    }
  obj = obj[args[i]];
 }
  return true;
}

var test = {level1:{level2:{level3:'level3'}} };

checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false

jsFiddle : https://jsfiddle.net/nikdtu/kjsxnunp/

not out of the box.

var string = function(v){ return v == null? "": String(v) }  //because I usually want this behaviour

var fetch = function(path, obj){
    path instanceof Array || (path = string(path).split('.'));
    for(var i=0, v=obj; i<path.length; v = v[path[i++]])
        if(v == null) return void 0;
    return v;
}

and your code:

if(fetch("object.foo", app)){
    alert(app.object.foo.bar);
}

or even more direct:

alert( fetch("object.foo.bar", app) );
//will alert undefined, if the path could not be resolved

Argument order is this way around, because this function is usually curried in my code, so I can do sth like:

arr.map(fetch('some.deeper.path'));

Slightly shorter (than original) way in JavaScript (less readable)

if ((a = app) && (o = a.object) && (f = o.foo)) {
  alert(f.bar);
}

The way I'd write it in CoffeeScript (my preferred method)

alert f.bar if f = app?.object?.foo?

If you're really into using Javascript and want it to appear clean, you could use something like:

function ifExist (name) { // Returns undefined if it doesn't exist
  arr = name.split('.');
  obj = eval('if (typeof '+(x = arr.splice(0,1)[0])+' !== \'undefined\') '+x);
  for (i = 0; i < arr.length; i++) {
    if (typeof obj === 'undefined') {
      return obj;
    }
    else {
      obj = obj[arr[i]];
    }
  }
  return obj
}

alert(ifExist('app.object.foo.bar'));

Because it uses eval, it could pose a security risk if app.object.foo.bar is generated by a the user. It works in simple cases (such as the one you posted above), but using something like app.object['foo'].bar in it would probably break it without adding some input checks.

发布评论

评论列表(0)

  1. 暂无评论