"this" JavaScript 模块中的关键字



我已经全局定义了以下模块:

var module = (function () {
  console.log(this);
  this.fn = function () {
    console.log(this);
  }
  return this;
})();

http://www.quirksmode.org/js/this.html:

In JavaScript |this| always refers to the “owner” of the function we're executing, or rather, to the object that a function is a method of.

console.log的第一个调用将Window记录为this的值,我理解这一点。但是,对console.log的第二次调用也是如此。

既然this指的是函数的所有者,为什么module.fn记录Window而不是module

当我调用fn时,我仍然要写module.fn,我不能写Window.fn。由于this指的是Window,我觉得这很令人困惑。

编辑:在我的示例中,我忘记返回this

既然这是指函数的所有者,为什么module.fn记录窗口而不是模块?

外部函数的返回值是window,因为它在任何特定的上下文中都不会被调用,所以module最终也是window

您应用模块模式的方式似乎是错误的。它应该返回在代码的其余部分中使用的公共接口:

var module = (function () {
  console.log(this);
  // public interface
  return {
    fn: function () {
      console.log(this);
    }
  }
})();
module.fn(); // "Object {fn: function}"

在您的示例中,全局对象接收fn。在浏览器的情况下,它是window对象。这是因为在没有特定上下文的情况下调用函数(有效地构建了一个新的作用域)。最后,module对象只是对window的引用(因为return this;)。

什么是this

在JavaScript中,this是当前上下文,即在特定时间调用函数的对象。它不是函数的"持有者"。您总是可以从其他对象中"窃取"该方法,并将其apply(字面上)保存到自己的对象中。

假设您出于某种原因想要对arguments对象进行切片。它看起来就像一个数组,但它不是一个数组。arguments.slice(2,4)不起作用(假设ECMAScript<5)。该怎么办?

Array.prototype.slice.apply(arguments, [2,4]);

您需要从Array原型中窃取slice函数,并在参数中使用if。在slice调用中,"this"是特定时间的arguments对象。

如何构造一个有效的模块

您的工作是return模块对象。你不想弄乱上下文。只要您没有将函数直接应用于模块对象,它就不相关。

最简单的解决方案就是最简单的。

var module = (function() {
   // do something internally, great for "private" stuff
   // then return the "public" interface
   return {
       doSomething: function() {
          // do something
       },
       introduce: function() {
           console.log(this);
       }
   };
})();
module.introduce(); // Object {doSomething: function, introduce: function}
module.doSomething();

相反

或者,如果你真的想的话,你可以使用this来完成你的工作,使用apply

var module = {};
(function(){
   this.doSomething = function() {
      // do something
   };
   this.introduce = function() {
       console.log(this);
   };
}).apply(module);
module.introduce(); // Object {doSomething: function, introduce: function}
module.doSomething();

请注意,这几乎等于"新"调用。

有更多同样有效的方法可以做到这一点,但第一种方法经常使用,而且非常清晰。无论如何,一切都取决于您的代码约定。

您的模式是错误的,您正在做的是创建一个封闭的作用域,并将module设置为该作用域的返回值:

// This is the design pattern:
var module = (function () {
  var module = {};
  var localVar = 1;
  module.moduleVar = 2;
  module.fn = function () {
    console.log(this);
  }

  return module;
})();
console.log(module.fn); // function() { console.log(this) ;}
console.log(module.moduleVar); // 2
console.log(module.localVar); // undefined

最新更新