2015-04-07 56 views
1

我试图理解为什么其中一个版本可以工作而另一个没有。为什么做出getConfigFails作业是非法的?与闭包共享构造函数参数

var MyClass = (function(){ 
    var _config; 
    function MyClass(config){ 
     _config = config; 
    } 
    MyClass.prototype.getConfigWorks = function(){ 
     _config.getConfigWorks(); 
    } 
    //Uncaught TypeError: Cannot read property 'getConfigFails' of undefined 
    MyClass.prototype.getConfigFails = _config.getConfigFails; 
    return MyClass; 
})(); 
var myClass = new MyClass({ 
    getConfigWorks:function(){ 
     console.log('no errors here'); 
    }, 
    getConfigFails: function(){ console.log('fail')} 
}); 

console.log(myClass); 
+1

在'MyClass.prototype.getConfigFails = _config.getConfigFails;'处设置一个断点,然后检查'_config'的值。 –

+0

然后灯泡亮起。闭包立即执行,真正的构造函数尚未被调用,所以它的参数是未定义的。 – wootscootinboogie

回答

1

你应该首先注意你的构造不是(function(){})()功能,而是function MyClass(){}功能。外部的自我调用功能仅仅是为了创建一个封闭,以使私人的_config

知道这一点。很显然,如果我们不关心_config是不是私人的,那么代码也应该可以工作?也就是说,如果_config是全局变量,则逻辑相同。

所以,如果我们可以让_config是全球性的,你的代码是完全一样的:

var _config; 
function InnerClass(config){ 
    _config = config; 
} 
InnerClass.prototype.getConfigWorks = function(){ 
    _config.getConfigWorks(); 
} 
//Uncaught TypeError: Cannot read property 'getConfigFails' of undefined 
InnerClass.prototype.getConfigFails = _config.getConfigFails; 

var MyClass = InnerClass; 

var myClass = new MyClass({ 
    getConfigWorks:function(){ 
     console.log('no errors here'); 
    }, 
    getConfigFails: function(){ console.log('fail')} 
}); 

console.log(myClass); 

这样写的。这很明显为什么_config.getConfigFails未定义。这是因为你没有分配任何东西。

重要的是要记住,调用new MyClass()只是调用构造函数,而不是调用它的任何代码。因此,如果在IIFE中重新包装上述代码,则逻辑不会更改,只会调用构造函数,而不是IIFE。

+0

解决方法应该很明显 - 将这些功能直接附加到'this'而不是'.prototype'。但是,如果不清楚,只是在评论中提及它,我可以在答案本身中添加解决方法 – slebetman

+0

这是一个专门尝试使用原型的练习,这正是我试图避免的,添加了不同的副本函数为每个对象。 – wootscootinboogie

+0

我没有把所有的东西放在一起。我知道IIFE不是构造函数,但它确实立即执行并为未定义的内容分配任务! :) – wootscootinboogie