关闭不起作用

时间:2010-04-07 18:34:00

标签: javascript

var Dog = function() {

    var _instance = 'hello world';

    return function() {
        console.log(this._instance);
    }
} (); //note that it is self invoking function

var l = new Dog(); //#> undefined 

在上述情况下,我期待输出:

  

'你好世界'

为什么this._instance没有访问应该可以通过闭包访问的变量?我在FF中对此进行了测试,并且未定义。

5 个答案:

答案 0 :(得分:11)

您没有为对象分配_instance,它只是一个闭包变量,应该在不使用this的情况下访问:

var Dog = function() {

    var _instance = 'hello world';

    return function() {
        console.log(_instance);
    }
} (); //note that it is self invoking function

var l = new Dog();

我可能会这样写:

var Dog = (function() {

    var defaults = {
       name: 'Rags'
    };

    var Dog = function (options) {
        // Take options as a constructor argument, this
        // allows you to merge it with defaults to override
        // options on specific instances
        this.setOptions(options);
    };

    Dog.prototype = {
       // Common methods for Dogs here
       setOptions: function (options) {
          // Declare all variables in the beginning of the method because
          // JavaScript hoists variable declarations
          var key = null;
          // First assign all the defaults to this object
          for ( key in defaults) {
             this[key] = defaults[key];
          }
          // Now override with the values in options:
          if (options && options.hasOwnProperty) {
             for ( key in options ) {
                this[key] = options[key];
             }
          }
       }
    };

    return Dog; // Return the constructor method 
} ()); // wrap the self-invoked function in paranthesis to visualize that
       // it creates a closure

var buster = new Dog({name: 'Buster'}),
    unnamed = new Dog();

alert(buster.name); // Alerts 'Buster'
alert(unnamed.name); // Alerts 'Rags'

请注意,我没有尝试编译上面的代码,因此可能包含一些错误。但JsLint无法处理任何事情!

您可能需要考虑向setOptions方法添加过滤,以便它不会分配您不想要的属性,或者过滤掉options-parameter中声明的方法等。

此外,如果您使用JQuery或类似的库,则有(通常)实用程序函数用于合并对象,这使得编写setOptions-method变得很简单:

function setOptions (options) {
   // I assume JQuery here
   // true as the first argument gives us a recursive merge
   var mergedOptions = $.extend(true, defaults, options);
   for (var key in mergedOptions ) {
      if(this.checkAllowedProperty(key, typeof(mergedOptions[key])) {
         this[key] = mergedOptions[key];
      }
   }
}

/**
 * This method checks if propertyName is an allowed property on this object.
 * If dataType is supplied it also checks if propertyName is allowed for
 * dataType
 * @return true if propertyName, with type dataType, is allowed on this object,
 * else false
 */
function checkAllowedProperty (propertyName, dataType);

答案 1 :(得分:6)

您的问题是this

答案 2 :(得分:4)

this._instance更改为_instance。您可能还希望将自调用函数包装在(function() { ... })();等括号中,以实现最大的浏览器兼容性。

答案 3 :(得分:2)

正如其他人所说,你需要删除“这个”。从你的功能。

问题的原因在于两个函数上下文中“this”关键字的绑定。在闭包内部,“this”指的是返回的函数,而不是外部函数。您可以通过执行以下操作来解决此问题:

var Dog = function() {

    var _instance = 'hello world';
    var that = this;  //Assign "this" to "that"

    return function() {
        console.log(that._instance);  //Use reference to "that"
    }
} ();

var l = new Dog();

您也可以使用function.apply()方法做些更接近的事情,但我会留给您。

我希望有所帮助。

答案 4 :(得分:1)

也许您对删除“this”感到满意,但您可能有兴趣了解“这个”并不是指您想要的东西。它所指的实际取决于函数的调用方式。它不一定是指由您返回的函数或其容器函数或任何其他对象构造的对象的实例。默认情况下,如果您只是将函数作为普通函数调用,则“this”将引用全局窗口上下文。

将“this”绑定到任何特定对象必须做的是将函数作为该对象方法或其原型调用。例如foo.myMethod()。另一种方法是您可以使用apply或call方法,传入您想要应用的对象。例如anyFunction.apply(富)。