在jQuery中使用字符串调用嵌套对象函数

时间:2014-12-13 21:08:35

标签: javascript jquery object

我的代码本身非常好用:

var Person = {
    getName: function() {
        alert("Johnny");
    }
};

var myContext = "Person";
var theCodeToExecute = myContext + ".getName()";
var theFunctionItself = new Function(theCodeToExecute);
theFunctionItself(); 

但是当我把它放在jQuery中时,它就会停止工作。

$(document).ready(function() {
    //Where the code should be.
});

我知道已经回答了非常相似的问题,但没有一个问题解决了这个问题。

编辑:

感谢大家的回答。我想我已经把我的问题缩小了很多,以至于我的意图非常清楚。这是我想要实现的更清晰的版本:

var Road = {
       House: function(color, size, neighbor){
          this.color = color;
          this.size = size;
          this.neighbor = neighbor;
       }
};

Road.House.prototype.getSize = function() {
    alert(this.size);
};

Road.House.prototype.getNeighborSize = function() {
    var theNeighbor = this.neighbor;
    var codeToExecute = theNeighbor + ".getSize()";
    var tmpFunc = new Function(codeToExecute);
    tmpFunc();    //this only works when outside of jQuery.    
};

var house1 = new Road.House("blue", "small", "house2");

var house2 = new Road.House("red", "huge", "house3");

house1.getNeighborSize(); //this successfully returns "huge" when outside of jQuery.

同样,这本身非常好用,但在jQuery中不起作用,我需要它在jQuery中工作,因为我的函数的最终版本将使用大量的jQuery代码。再次感谢!

最后编辑:

感谢Felix的出色帮助。似乎有一个最后的问题。如果在我正在查询的房子之前宣布邻居,我只能得到邻居的大小。

var house1 = new Road.House("red", "big", house2);
var house2 = new Road.House("blue", "huge", house3);
var house4 = new Road.House("blue", "small", house4);
var house3 = new Road.House("blue", "little", house1);

house1.getNeighborSize(); //this doesn't work.

house3.getNeighborSize(); //this works

再次感谢!!

2 个答案:

答案 0 :(得分:4)

使用new Function创建功能时,将在全局范围中创建该功能。 即它无法访问您在内部 ready回调中创建的变量。

// global scope

$(document).ready(function() {

   // ready callback scope    

});

引用MDN这里的黄色大框:

  

注意 :使用Function构造函数创建的函数不会为其创建上下文创建闭包;它们总是在全球范围内创建。运行它们时,它们只能访问自己的局部变量和全局变量,而不能访问调用Function构造函数的范围。这与使用eval和函数表达式代码不同。

解决方案:

  1. 在全局范围内创建Person
  2. 使用eval代替new Function
  3. 最好的:

    1. 不要动态评估代码。你可以直接写Person.getName()
    2. 即使你认为你必须评估代码,你可能不会,但如果你不解释你真正想要实现的目标,我们无法帮你找到替代方案。


      那么,解决问题的方法不是尝试动态引用变量,而是将对邻居的引用传递给构造函数:

      var house2 = new Road.House("red", "huge");
      var house1 = new Road.House("red", "huge", house2);
      

      然后该函数看起来像

      Road.House.prototype.getNeighborSize = function() {
          if (this.neighbor) {
              this.neighbor.getSize();
          } 
      };
      

      如果在构建时无法传递对邻居的引用,则可以创建一个setter:

      Road.House.prototype.setNeighbor = function(neighbor) {
          this.neighbor = neighbor;
      };
      

答案 1 :(得分:0)

好吧,如果您尝试调用某个方法,则会出现一些错误。正如费利克斯所提到的,你应该避免像这样动态评估Javascript。首先,假设您只想调用getName方法,我将从更正后的代码开始。

$(document).ready(function() {

    var Person = {
    getName: function() {
        alert("Johnny");
    }
};

Person.getName();


});

您无需将Person重新分配给新变量,您可以直接在此处访问它。您还将Person放在引号中,这意味着您的myContext变量引用了一个字符串,其中包含单词" Person"。

现在,我认为你真正想要做的是构建一个构造函数,从你使用new开始。

http://jsfiddle.net/2v0xnoyf/

以下是实际完成的方式:

$(document).ready(function () {

    //You need to make it a function that returns an object
    var Person = function (name) {

        return {

            getName: function () {
                alert(name);
            }

        }

    };

    //Then we create an instance of Person and pass in the name as an argument
   var johnny = new Person('Johnny');
    johnny.getName();


});

您将看到,不是将Person设为对象,而是将其作为返回对象的函数,并使用函数参数作为名称的占位符。通过这种方式,我们可以创建尽可能多的人,而且我们不必每次都重新定义Person。例如,如果我们想要再创造一些人,我们就是这样做:

var sam = new Person('Sam');
var jim = new Person('Jim');

现在sam.getName()会警告Sam'和jim.getName()会警告Jim'。