如何通过其名称字符串找到'type'(对象的构造函数)?

时间:2014-04-04 03:54:20

标签: javascript types constructor deserialization

我正在尝试在JSON / YAML中存储Mongoose架构。因此,我必须存储'类型'作为他们名字的字符串。

UserSchema = new mongoose.Schema({
  name: {
    type: String, required: true
  },
  ip: [
    { type: Number, required: true, min: 0, max: 255 },
    { type: Number, required: true, min: 0, max: 255 },
    { type: Number, required: true, min: 0, max: 255 },
    { type: Number, required: true, min: 0, max: 255 }
  ]
});

将存储为:

%YAML 1.2
---
name:
  type: String
  required: true
ip:
  - &ip
    type: Number
    required: true
    min: 0
    max: 255
  - *ip
  - *ip
  - *ip

因此,我必须找到'类型' (对象的构造函数)由其名称的字符串组成。使用eval的方法很讨厌,但说明了我想要实现的目标。

不要再投票了,我正在改进之前提出的问题,以便将来对读者有用。我不打算使用eval,这只是一个例子。

// #1 - simple 'type'
eval('Date');

// #2 - scoped 'type'
try {
  eval('google.maps.Marker');
} catch(e) {
  // failed
}

1 个答案:

答案 0 :(得分:0)

我正在回答我的问题。

JavaScript中的'type'基本上是顶级作用域或另一个对象中的构造函数。因此,可以将“类型”解析为普通属性。如果它是嵌套的,则需要递归/循环。

递归解决方案:

function Type(name, scope) {
  if (scope == null) {
    // Resolve the top-level scope
    if (typeof window !== "undefined" && window !== null) {
      // Browser
      scope = window;
    } else if (typeof global !== "undefined" && global !== null) {
      // Node.js
      scope = global;
    }
  }

  // Check if name is nested
  var indexOfDot = name.indexOf('.');
  if (indexOfDot !== -1) {
    // Recursively resolve the type
    var nextScope = scope[name.slice(0, indexOfDot)],
        nextName  = name.slice(indexOfDot + 1);

    if (Object.prototype.toString.call(nextScope) !== '[object Object]') {
      return Type(nextName, nextScope);
    }
  }
  else {
    var type = scope[name];
    if (typeof type === 'function') {
      return type;
    }
  }

  // Return null if failed
  return null;
}

迭代解决方案:

function Type(name, scope) {
  if (scope == null) {
    // Resolve the top-level scope
    if (typeof window !== "undefined" && window !== null) {
      // Browser
      scope = window;
    } else if (typeof global !== "undefined" && global !== null) {
      // Node.js
      scope = global;
    }
  }

  // Iterate and resolve the type
  name = name.split('.');
  while (name.length > 1) {
    scope = scope[name.shift()];

    // Return null if failed
    if (Object.prototype.toString.call(scope) !== '[object Object]') {
      return null;
    }
  }

  var type = scope[name[0]];
  if (typeof type === 'function') {
    return type;
  }

  // Return null if failed
  return null;
}